blob: 98e9df3556e71504063b4ac3c59d4f6775cb2451 [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 Hedberg84bde9d2012-01-25 14:21:06 +0200428 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_SSP;
Johan 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 Hedberg84bde9d2012-01-25 14:21:06 +0200762 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200765 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
768 memset(&cp, 0, sizeof(cp));
769
770 create_eir(hdev, cp.data);
771
772 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500773 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300774
775 memcpy(hdev->eir, cp.data, sizeof(cp.data));
776
Johan Hedberg890ea892013-03-15 17:06:52 -0500777 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300778}
779
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200780static u8 get_service_classes(struct hci_dev *hdev)
781{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300782 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783 u8 val = 0;
784
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200787
788 return val;
789}
790
Johan Hedberg890ea892013-03-15 17:06:52 -0500791static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200792{
Johan Hedberg890ea892013-03-15 17:06:52 -0500793 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200794 u8 cod[3];
795
796 BT_DBG("%s", hdev->name);
797
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200798 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500799 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200800
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300801 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
802 return;
803
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200804 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500805 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200806
807 cod[0] = hdev->minor_class;
808 cod[1] = hdev->major_class;
809 cod[2] = get_service_classes(hdev);
810
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700811 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
812 cod[1] |= 0x20;
813
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500815 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200816
Johan Hedberg890ea892013-03-15 17:06:52 -0500817 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200818}
819
Johan Hedberga4858cb2014-02-25 19:56:31 +0200820static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200821{
822 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200823
824 /* If there's a pending mgmt command the flag will not yet have
825 * it's final value, so check for this first.
826 */
827 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
828 if (cmd) {
829 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200830 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200831 }
832
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834}
835
836static void enable_advertising(struct hci_request *req)
837{
838 struct hci_dev *hdev = req->hdev;
839 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200840 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200841 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200842
Johan Hedberg8d972502014-02-28 12:54:14 +0200843 /* Clear the HCI_ADVERTISING bit temporarily so that the
844 * hci_update_random_address knows that it's safe to go ahead
845 * and write a new random address. The flag will be set back on
846 * as soon as the SET_ADV_ENABLE HCI command completes.
847 */
848 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
849
Johan Hedberga4858cb2014-02-25 19:56:31 +0200850 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200851
Johan Hedberga4858cb2014-02-25 19:56:31 +0200852 /* Set require_privacy to true only when non-connectable
853 * advertising is used. In that case it is fine to use a
854 * non-resolvable private address.
855 */
856 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200857 return;
858
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800859 memset(&cp, 0, sizeof(cp));
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200860 cp.min_interval = __constant_cpu_to_le16(0x0800);
861 cp.max_interval = __constant_cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200862 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200863 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200864 cp.channel_map = hdev->le_adv_channel_map;
865
866 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
867
868 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
869}
870
871static void disable_advertising(struct hci_request *req)
872{
873 u8 enable = 0x00;
874
875 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
876}
877
Johan Hedberg7d785252011-12-15 00:47:39 +0200878static void service_cache_off(struct work_struct *work)
879{
880 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300881 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500882 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200883
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200884 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200885 return;
886
Johan Hedberg890ea892013-03-15 17:06:52 -0500887 hci_req_init(&req, hdev);
888
Johan Hedberg7d785252011-12-15 00:47:39 +0200889 hci_dev_lock(hdev);
890
Johan Hedberg890ea892013-03-15 17:06:52 -0500891 update_eir(&req);
892 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200893
894 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500895
896 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200897}
898
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200899static void rpa_expired(struct work_struct *work)
900{
901 struct hci_dev *hdev = container_of(work, struct hci_dev,
902 rpa_expired.work);
903 struct hci_request req;
904
905 BT_DBG("");
906
907 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
908
909 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
910 hci_conn_num(hdev, LE_LINK) > 0)
911 return;
912
913 /* The generation of a new RPA and programming it into the
914 * controller happens in the enable_advertising() function.
915 */
916
917 hci_req_init(&req, hdev);
918
919 disable_advertising(&req);
920 enable_advertising(&req);
921
922 hci_req_run(&req, NULL);
923}
924
Johan Hedberg6a919082012-02-28 06:17:26 +0200925static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200926{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200927 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200928 return;
929
Johan Hedberg4f87da82012-03-02 19:55:56 +0200930 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200931 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200932
Johan Hedberg4f87da82012-03-02 19:55:56 +0200933 /* Non-mgmt controlled devices get this bit set
934 * implicitly so that pairing works for them, however
935 * for mgmt we require user-space to explicitly enable
936 * it
937 */
938 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200939}
940
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200941static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300942 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200943{
944 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200945
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200946 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200947
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300948 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200949
Johan Hedberg03811012010-12-08 00:21:06 +0200950 memset(&rp, 0, sizeof(rp));
951
Johan Hedberg03811012010-12-08 00:21:06 +0200952 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200953
954 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200955 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200956
957 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
958 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
959
960 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200961
962 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200963 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200964
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300965 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200966
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200967 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300968 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200969}
970
971static void mgmt_pending_free(struct pending_cmd *cmd)
972{
973 sock_put(cmd->sk);
974 kfree(cmd->param);
975 kfree(cmd);
976}
977
978static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300979 struct hci_dev *hdev, void *data,
980 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200981{
982 struct pending_cmd *cmd;
983
Andre Guedes12b94562012-06-07 19:05:45 -0300984 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200985 if (!cmd)
986 return NULL;
987
988 cmd->opcode = opcode;
989 cmd->index = hdev->id;
990
Andre Guedes12b94562012-06-07 19:05:45 -0300991 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200992 if (!cmd->param) {
993 kfree(cmd);
994 return NULL;
995 }
996
997 if (data)
998 memcpy(cmd->param, data, len);
999
1000 cmd->sk = sk;
1001 sock_hold(sk);
1002
1003 list_add(&cmd->list, &hdev->mgmt_pending);
1004
1005 return cmd;
1006}
1007
1008static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001009 void (*cb)(struct pending_cmd *cmd,
1010 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001011 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001012{
Andre Guedesa3d09352013-02-01 11:21:30 -03001013 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001014
Andre Guedesa3d09352013-02-01 11:21:30 -03001015 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001016 if (opcode > 0 && cmd->opcode != opcode)
1017 continue;
1018
1019 cb(cmd, data);
1020 }
1021}
1022
Johan Hedberg03811012010-12-08 00:21:06 +02001023static void mgmt_pending_remove(struct pending_cmd *cmd)
1024{
1025 list_del(&cmd->list);
1026 mgmt_pending_free(cmd);
1027}
1028
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001029static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001030{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001031 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001032
Johan Hedbergaee9b212012-02-18 15:07:59 +02001033 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001034 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001035}
1036
Johan Hedberg8b064a32014-02-24 14:52:22 +02001037static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1038{
1039 BT_DBG("%s status 0x%02x", hdev->name, status);
1040
Johan Hedberga3172b72014-02-28 09:33:44 +02001041 if (hci_conn_count(hdev) == 0) {
1042 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001043 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001044 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001045}
1046
1047static int clean_up_hci_state(struct hci_dev *hdev)
1048{
1049 struct hci_request req;
1050 struct hci_conn *conn;
1051
1052 hci_req_init(&req, hdev);
1053
1054 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1055 test_bit(HCI_PSCAN, &hdev->flags)) {
1056 u8 scan = 0x00;
1057 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1058 }
1059
1060 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1061 disable_advertising(&req);
1062
1063 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001064 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001065 }
1066
1067 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1068 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001069 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001070
Johan Hedbergc9910d02014-02-27 14:35:12 +02001071 switch (conn->state) {
1072 case BT_CONNECTED:
1073 case BT_CONFIG:
1074 dc.handle = cpu_to_le16(conn->handle);
1075 dc.reason = 0x15; /* Terminated due to Power Off */
1076 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1077 break;
1078 case BT_CONNECT:
1079 if (conn->type == LE_LINK)
1080 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1081 0, NULL);
1082 else if (conn->type == ACL_LINK)
1083 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1084 6, &conn->dst);
1085 break;
1086 case BT_CONNECT2:
1087 bacpy(&rej.bdaddr, &conn->dst);
1088 rej.reason = 0x15; /* Terminated due to Power Off */
1089 if (conn->type == ACL_LINK)
1090 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1091 sizeof(rej), &rej);
1092 else if (conn->type == SCO_LINK)
1093 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1094 sizeof(rej), &rej);
1095 break;
1096 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001097 }
1098
1099 return hci_req_run(&req, clean_up_hci_complete);
1100}
1101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001102static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001103 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001104{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001105 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001106 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001107 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001108
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001109 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001110
Johan Hedberga7e80f22013-01-09 16:05:19 +02001111 if (cp->val != 0x00 && cp->val != 0x01)
1112 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1113 MGMT_STATUS_INVALID_PARAMS);
1114
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001115 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001116
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001117 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1118 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1119 MGMT_STATUS_BUSY);
1120 goto failed;
1121 }
1122
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001123 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1124 cancel_delayed_work(&hdev->power_off);
1125
1126 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001127 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1128 data, len);
1129 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001130 goto failed;
1131 }
1132 }
1133
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001134 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001135 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001136 goto failed;
1137 }
1138
Johan Hedberg03811012010-12-08 00:21:06 +02001139 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1140 if (!cmd) {
1141 err = -ENOMEM;
1142 goto failed;
1143 }
1144
Johan Hedberg8b064a32014-02-24 14:52:22 +02001145 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001146 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001147 err = 0;
1148 } else {
1149 /* Disconnect connections, stop scans, etc */
1150 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001151 if (!err)
1152 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1153 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Johan Hedberg8b064a32014-02-24 14:52:22 +02001155 /* ENODATA means there were no HCI commands queued */
1156 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001157 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001158 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1159 err = 0;
1160 }
1161 }
Johan Hedberg03811012010-12-08 00:21:06 +02001162
1163failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001164 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001165 return err;
1166}
1167
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001168static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1169 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001170{
1171 struct sk_buff *skb;
1172 struct mgmt_hdr *hdr;
1173
Andre Guedes790eff42012-06-07 19:05:46 -03001174 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001175 if (!skb)
1176 return -ENOMEM;
1177
1178 hdr = (void *) skb_put(skb, sizeof(*hdr));
1179 hdr->opcode = cpu_to_le16(event);
1180 if (hdev)
1181 hdr->index = cpu_to_le16(hdev->id);
1182 else
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05301183 hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001184 hdr->len = cpu_to_le16(data_len);
1185
1186 if (data)
1187 memcpy(skb_put(skb, data_len), data, data_len);
1188
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001189 /* Time stamp */
1190 __net_timestamp(skb);
1191
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001192 hci_send_to_control(skb, skip_sk);
1193 kfree_skb(skb);
1194
1195 return 0;
1196}
1197
1198static int new_settings(struct hci_dev *hdev, struct sock *skip)
1199{
1200 __le32 ev;
1201
1202 ev = cpu_to_le32(get_current_settings(hdev));
1203
1204 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1205}
1206
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001207struct cmd_lookup {
1208 struct sock *sk;
1209 struct hci_dev *hdev;
1210 u8 mgmt_status;
1211};
1212
1213static void settings_rsp(struct pending_cmd *cmd, void *data)
1214{
1215 struct cmd_lookup *match = data;
1216
1217 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1218
1219 list_del(&cmd->list);
1220
1221 if (match->sk == NULL) {
1222 match->sk = cmd->sk;
1223 sock_hold(match->sk);
1224 }
1225
1226 mgmt_pending_free(cmd);
1227}
1228
1229static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1230{
1231 u8 *status = data;
1232
1233 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1234 mgmt_pending_remove(cmd);
1235}
1236
Johan Hedberge6fe7982013-10-02 15:45:22 +03001237static u8 mgmt_bredr_support(struct hci_dev *hdev)
1238{
1239 if (!lmp_bredr_capable(hdev))
1240 return MGMT_STATUS_NOT_SUPPORTED;
1241 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1242 return MGMT_STATUS_REJECTED;
1243 else
1244 return MGMT_STATUS_SUCCESS;
1245}
1246
1247static u8 mgmt_le_support(struct hci_dev *hdev)
1248{
1249 if (!lmp_le_capable(hdev))
1250 return MGMT_STATUS_NOT_SUPPORTED;
1251 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1252 return MGMT_STATUS_REJECTED;
1253 else
1254 return MGMT_STATUS_SUCCESS;
1255}
1256
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001257static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1258{
1259 struct pending_cmd *cmd;
1260 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001261 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001262 bool changed;
1263
1264 BT_DBG("status 0x%02x", status);
1265
1266 hci_dev_lock(hdev);
1267
1268 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1269 if (!cmd)
1270 goto unlock;
1271
1272 if (status) {
1273 u8 mgmt_err = mgmt_status(status);
1274 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001275 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001276 goto remove_cmd;
1277 }
1278
1279 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001280 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001281 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1282 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001283
1284 if (hdev->discov_timeout > 0) {
1285 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1286 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1287 to);
1288 }
1289 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001290 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1291 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001292 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001293
1294 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1295
1296 if (changed)
1297 new_settings(hdev, cmd->sk);
1298
Marcel Holtmann970ba522013-10-15 06:33:57 -07001299 /* When the discoverable mode gets changed, make sure
1300 * that class of device has the limited discoverable
1301 * bit correctly set.
1302 */
1303 hci_req_init(&req, hdev);
1304 update_class(&req);
1305 hci_req_run(&req, NULL);
1306
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001307remove_cmd:
1308 mgmt_pending_remove(cmd);
1309
1310unlock:
1311 hci_dev_unlock(hdev);
1312}
1313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001314static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001315 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001316{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001317 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001318 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001319 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001320 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001321 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001322 int err;
1323
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001324 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001325
Johan Hedberg9a43e252013-10-20 19:00:07 +03001326 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1327 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001328 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001329 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001330
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001331 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001332 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1333 MGMT_STATUS_INVALID_PARAMS);
1334
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001335 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001336
1337 /* Disabling discoverable requires that no timeout is set,
1338 * and enabling limited discoverable requires a timeout.
1339 */
1340 if ((cp->val == 0x00 && timeout > 0) ||
1341 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001342 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001343 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001344
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001345 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001346
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001347 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001348 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001349 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001350 goto failed;
1351 }
1352
1353 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001354 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001355 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001356 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001357 goto failed;
1358 }
1359
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001360 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001361 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001362 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001363 goto failed;
1364 }
1365
1366 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001367 bool changed = false;
1368
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001369 /* Setting limited discoverable when powered off is
1370 * not a valid operation since it requires a timeout
1371 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1372 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001373 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1374 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1375 changed = true;
1376 }
1377
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001378 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001379 if (err < 0)
1380 goto failed;
1381
1382 if (changed)
1383 err = new_settings(hdev, sk);
1384
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001385 goto failed;
1386 }
1387
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001388 /* If the current mode is the same, then just update the timeout
1389 * value with the new value. And if only the timeout gets updated,
1390 * then no need for any HCI transactions.
1391 */
1392 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1393 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1394 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001395 cancel_delayed_work(&hdev->discov_off);
1396 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001397
Marcel Holtmann36261542013-10-15 08:28:51 -07001398 if (cp->val && hdev->discov_timeout > 0) {
1399 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001400 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001401 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001402 }
1403
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001404 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001405 goto failed;
1406 }
1407
1408 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1409 if (!cmd) {
1410 err = -ENOMEM;
1411 goto failed;
1412 }
1413
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001414 /* Cancel any potential discoverable timeout that might be
1415 * still active and store new timeout value. The arming of
1416 * the timeout happens in the complete handler.
1417 */
1418 cancel_delayed_work(&hdev->discov_off);
1419 hdev->discov_timeout = timeout;
1420
Johan Hedbergb456f872013-10-19 23:38:22 +03001421 /* Limited discoverable mode */
1422 if (cp->val == 0x02)
1423 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1424 else
1425 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1426
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001427 hci_req_init(&req, hdev);
1428
Johan Hedberg9a43e252013-10-20 19:00:07 +03001429 /* The procedure for LE-only controllers is much simpler - just
1430 * update the advertising data.
1431 */
1432 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1433 goto update_ad;
1434
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001435 scan = SCAN_PAGE;
1436
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001437 if (cp->val) {
1438 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001439
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001440 if (cp->val == 0x02) {
1441 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001442 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001443 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1444 hci_cp.iac_lap[1] = 0x8b;
1445 hci_cp.iac_lap[2] = 0x9e;
1446 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1447 hci_cp.iac_lap[4] = 0x8b;
1448 hci_cp.iac_lap[5] = 0x9e;
1449 } else {
1450 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001451 hci_cp.num_iac = 1;
1452 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1453 hci_cp.iac_lap[1] = 0x8b;
1454 hci_cp.iac_lap[2] = 0x9e;
1455 }
1456
1457 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1458 (hci_cp.num_iac * 3) + 1, &hci_cp);
1459
1460 scan |= SCAN_INQUIRY;
1461 } else {
1462 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1463 }
1464
1465 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001466
Johan Hedberg9a43e252013-10-20 19:00:07 +03001467update_ad:
1468 update_adv_data(&req);
1469
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001470 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001471 if (err < 0)
1472 mgmt_pending_remove(cmd);
1473
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001474failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001475 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001476 return err;
1477}
1478
Johan Hedberg406d7802013-03-15 17:07:09 -05001479static void write_fast_connectable(struct hci_request *req, bool enable)
1480{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001481 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001482 struct hci_cp_write_page_scan_activity acp;
1483 u8 type;
1484
Johan Hedberg547003b2013-10-21 16:51:53 +03001485 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1486 return;
1487
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001488 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1489 return;
1490
Johan Hedberg406d7802013-03-15 17:07:09 -05001491 if (enable) {
1492 type = PAGE_SCAN_TYPE_INTERLACED;
1493
1494 /* 160 msec page scan interval */
1495 acp.interval = __constant_cpu_to_le16(0x0100);
1496 } else {
1497 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1498
1499 /* default 1.28 sec page scan */
1500 acp.interval = __constant_cpu_to_le16(0x0800);
1501 }
1502
1503 acp.window = __constant_cpu_to_le16(0x0012);
1504
Johan Hedbergbd98b992013-03-15 17:07:13 -05001505 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1506 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1507 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1508 sizeof(acp), &acp);
1509
1510 if (hdev->page_scan_type != type)
1511 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001512}
1513
Johan Hedberg2b76f452013-03-15 17:07:04 -05001514static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1515{
1516 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001517 struct mgmt_mode *cp;
1518 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001519
1520 BT_DBG("status 0x%02x", status);
1521
1522 hci_dev_lock(hdev);
1523
1524 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1525 if (!cmd)
1526 goto unlock;
1527
Johan Hedberg37438c12013-10-14 16:20:05 +03001528 if (status) {
1529 u8 mgmt_err = mgmt_status(status);
1530 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1531 goto remove_cmd;
1532 }
1533
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001534 cp = cmd->param;
1535 if (cp->val)
1536 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1537 else
1538 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1539
Johan Hedberg2b76f452013-03-15 17:07:04 -05001540 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1541
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001542 if (changed)
1543 new_settings(hdev, cmd->sk);
1544
Johan Hedberg37438c12013-10-14 16:20:05 +03001545remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001546 mgmt_pending_remove(cmd);
1547
1548unlock:
1549 hci_dev_unlock(hdev);
1550}
1551
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001552static int set_connectable_update_settings(struct hci_dev *hdev,
1553 struct sock *sk, u8 val)
1554{
1555 bool changed = false;
1556 int err;
1557
1558 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1559 changed = true;
1560
1561 if (val) {
1562 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1563 } else {
1564 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1565 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1566 }
1567
1568 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1569 if (err < 0)
1570 return err;
1571
1572 if (changed)
1573 return new_settings(hdev, sk);
1574
1575 return 0;
1576}
1577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001578static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001579 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001580{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001581 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001582 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001583 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001584 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001585 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001586
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001587 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001588
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001589 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1590 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001591 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001592 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001593
Johan Hedberga7e80f22013-01-09 16:05:19 +02001594 if (cp->val != 0x00 && cp->val != 0x01)
1595 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1596 MGMT_STATUS_INVALID_PARAMS);
1597
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001598 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001599
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001600 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001601 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001602 goto failed;
1603 }
1604
1605 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001606 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001607 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001608 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001609 goto failed;
1610 }
1611
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001612 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1613 if (!cmd) {
1614 err = -ENOMEM;
1615 goto failed;
1616 }
1617
Johan Hedberg2b76f452013-03-15 17:07:04 -05001618 hci_req_init(&req, hdev);
1619
Johan Hedberg9a43e252013-10-20 19:00:07 +03001620 /* If BR/EDR is not enabled and we disable advertising as a
1621 * by-product of disabling connectable, we need to update the
1622 * advertising flags.
1623 */
1624 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1625 if (!cp->val) {
1626 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1627 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1628 }
1629 update_adv_data(&req);
1630 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001631 if (cp->val) {
1632 scan = SCAN_PAGE;
1633 } else {
1634 scan = 0;
1635
1636 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001637 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001638 cancel_delayed_work(&hdev->discov_off);
1639 }
1640
1641 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1642 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001643
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001644 /* If we're going from non-connectable to connectable or
1645 * vice-versa when fast connectable is enabled ensure that fast
1646 * connectable gets disabled. write_fast_connectable won't do
1647 * anything if the page scan parameters are already what they
1648 * should be.
1649 */
1650 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001651 write_fast_connectable(&req, false);
1652
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001653 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1654 hci_conn_num(hdev, LE_LINK) == 0) {
1655 disable_advertising(&req);
1656 enable_advertising(&req);
1657 }
1658
Johan Hedberg2b76f452013-03-15 17:07:04 -05001659 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001660 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001661 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001662 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001663 err = set_connectable_update_settings(hdev, sk,
1664 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001665 goto failed;
1666 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001667
1668failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001669 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001670 return err;
1671}
1672
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001673static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001674 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001675{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001676 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001677 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001678 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001679
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001680 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001681
Johan Hedberga7e80f22013-01-09 16:05:19 +02001682 if (cp->val != 0x00 && cp->val != 0x01)
1683 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1684 MGMT_STATUS_INVALID_PARAMS);
1685
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001686 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001687
1688 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001689 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001690 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001691 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001692
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001693 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001694 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001695 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001696
Marcel Holtmann55594352013-10-06 16:11:57 -07001697 if (changed)
1698 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001699
Marcel Holtmann55594352013-10-06 16:11:57 -07001700unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001701 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001702 return err;
1703}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001704
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001705static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1706 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001707{
1708 struct mgmt_mode *cp = data;
1709 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001710 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001711 int err;
1712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001713 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001714
Johan Hedberge6fe7982013-10-02 15:45:22 +03001715 status = mgmt_bredr_support(hdev);
1716 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001717 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001718 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001719
Johan Hedberga7e80f22013-01-09 16:05:19 +02001720 if (cp->val != 0x00 && cp->val != 0x01)
1721 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1722 MGMT_STATUS_INVALID_PARAMS);
1723
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001724 hci_dev_lock(hdev);
1725
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001726 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001727 bool changed = false;
1728
1729 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001730 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001731 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1732 changed = true;
1733 }
1734
1735 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1736 if (err < 0)
1737 goto failed;
1738
1739 if (changed)
1740 err = new_settings(hdev, sk);
1741
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001742 goto failed;
1743 }
1744
1745 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001746 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001747 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001748 goto failed;
1749 }
1750
1751 val = !!cp->val;
1752
1753 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1754 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1755 goto failed;
1756 }
1757
1758 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1759 if (!cmd) {
1760 err = -ENOMEM;
1761 goto failed;
1762 }
1763
1764 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1765 if (err < 0) {
1766 mgmt_pending_remove(cmd);
1767 goto failed;
1768 }
1769
1770failed:
1771 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001772 return err;
1773}
1774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001775static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001776{
1777 struct mgmt_mode *cp = data;
1778 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001779 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001780 int err;
1781
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001782 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001783
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001784 status = mgmt_bredr_support(hdev);
1785 if (status)
1786 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1787
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001788 if (!lmp_ssp_capable(hdev))
1789 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1790 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001791
Johan Hedberga7e80f22013-01-09 16:05:19 +02001792 if (cp->val != 0x00 && cp->val != 0x01)
1793 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1794 MGMT_STATUS_INVALID_PARAMS);
1795
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001796 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001797
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001798 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001799 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001800
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001801 if (cp->val) {
1802 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1803 &hdev->dev_flags);
1804 } else {
1805 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1806 &hdev->dev_flags);
1807 if (!changed)
1808 changed = test_and_clear_bit(HCI_HS_ENABLED,
1809 &hdev->dev_flags);
1810 else
1811 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001812 }
1813
1814 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1815 if (err < 0)
1816 goto failed;
1817
1818 if (changed)
1819 err = new_settings(hdev, sk);
1820
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001821 goto failed;
1822 }
1823
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001824 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1825 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001826 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1827 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001828 goto failed;
1829 }
1830
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001831 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001832 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1833 goto failed;
1834 }
1835
1836 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1837 if (!cmd) {
1838 err = -ENOMEM;
1839 goto failed;
1840 }
1841
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001842 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001843 if (err < 0) {
1844 mgmt_pending_remove(cmd);
1845 goto failed;
1846 }
1847
1848failed:
1849 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001850 return err;
1851}
1852
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001853static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001854{
1855 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001856 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001857 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001858 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001859
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001860 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001861
Johan Hedberge6fe7982013-10-02 15:45:22 +03001862 status = mgmt_bredr_support(hdev);
1863 if (status)
1864 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001865
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001866 if (!lmp_ssp_capable(hdev))
1867 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1868 MGMT_STATUS_NOT_SUPPORTED);
1869
1870 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1871 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1872 MGMT_STATUS_REJECTED);
1873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Marcel Holtmannee392692013-10-01 22:59:23 -07001878 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001879
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001880 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001881 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001882 } else {
1883 if (hdev_is_powered(hdev)) {
1884 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1885 MGMT_STATUS_REJECTED);
1886 goto unlock;
1887 }
1888
Marcel Holtmannee392692013-10-01 22:59:23 -07001889 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001890 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001891
1892 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1893 if (err < 0)
1894 goto unlock;
1895
1896 if (changed)
1897 err = new_settings(hdev, sk);
1898
1899unlock:
1900 hci_dev_unlock(hdev);
1901 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001902}
1903
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001904static void le_enable_complete(struct hci_dev *hdev, u8 status)
1905{
1906 struct cmd_lookup match = { NULL, hdev };
1907
1908 if (status) {
1909 u8 mgmt_err = mgmt_status(status);
1910
1911 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1912 &mgmt_err);
1913 return;
1914 }
1915
1916 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1917
1918 new_settings(hdev, match.sk);
1919
1920 if (match.sk)
1921 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001922
1923 /* Make sure the controller has a good default for
1924 * advertising data. Restrict the update to when LE
1925 * has actually been enabled. During power on, the
1926 * update in powered_update_hci will take care of it.
1927 */
1928 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1929 struct hci_request req;
1930
1931 hci_dev_lock(hdev);
1932
1933 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001934 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001935 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001936 hci_req_run(&req, NULL);
1937
1938 hci_dev_unlock(hdev);
1939 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001940}
1941
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001942static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001943{
1944 struct mgmt_mode *cp = data;
1945 struct hci_cp_write_le_host_supported hci_cp;
1946 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001947 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001948 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001949 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001950
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001951 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001952
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001953 if (!lmp_le_capable(hdev))
1954 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1955 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001956
Johan Hedberga7e80f22013-01-09 16:05:19 +02001957 if (cp->val != 0x00 && cp->val != 0x01)
1958 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1959 MGMT_STATUS_INVALID_PARAMS);
1960
Johan Hedbergc73eee92013-04-19 18:35:21 +03001961 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001962 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001963 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1964 MGMT_STATUS_REJECTED);
1965
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001966 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001967
1968 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001969 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001970
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001971 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001972 bool changed = false;
1973
1974 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1975 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1976 changed = true;
1977 }
1978
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001979 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1980 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001981 changed = true;
1982 }
1983
Johan Hedberg06199cf2012-02-22 16:37:11 +02001984 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1985 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001986 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001987
1988 if (changed)
1989 err = new_settings(hdev, sk);
1990
Johan Hedberg1de028c2012-02-29 19:55:35 -08001991 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001992 }
1993
Johan Hedberg4375f102013-09-25 13:26:10 +03001994 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1995 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001996 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001997 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001998 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001999 }
2000
2001 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2002 if (!cmd) {
2003 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002004 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002005 }
2006
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002007 hci_req_init(&req, hdev);
2008
Johan Hedberg06199cf2012-02-22 16:37:11 +02002009 memset(&hci_cp, 0, sizeof(hci_cp));
2010
2011 if (val) {
2012 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002013 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002014 } else {
2015 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2016 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002017 }
2018
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002019 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2020 &hci_cp);
2021
2022 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302023 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002024 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002025
Johan Hedberg1de028c2012-02-29 19:55:35 -08002026unlock:
2027 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002028 return err;
2029}
2030
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002031/* This is a helper function to test for pending mgmt commands that can
2032 * cause CoD or EIR HCI commands. We can only allow one such pending
2033 * mgmt command at a time since otherwise we cannot easily track what
2034 * the current values are, will be, and based on that calculate if a new
2035 * HCI command needs to be sent and if yes with what value.
2036 */
2037static bool pending_eir_or_class(struct hci_dev *hdev)
2038{
2039 struct pending_cmd *cmd;
2040
2041 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2042 switch (cmd->opcode) {
2043 case MGMT_OP_ADD_UUID:
2044 case MGMT_OP_REMOVE_UUID:
2045 case MGMT_OP_SET_DEV_CLASS:
2046 case MGMT_OP_SET_POWERED:
2047 return true;
2048 }
2049 }
2050
2051 return false;
2052}
2053
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002054static const u8 bluetooth_base_uuid[] = {
2055 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2056 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2057};
2058
2059static u8 get_uuid_size(const u8 *uuid)
2060{
2061 u32 val;
2062
2063 if (memcmp(uuid, bluetooth_base_uuid, 12))
2064 return 128;
2065
2066 val = get_unaligned_le32(&uuid[12]);
2067 if (val > 0xffff)
2068 return 32;
2069
2070 return 16;
2071}
2072
Johan Hedberg92da6092013-03-15 17:06:55 -05002073static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2074{
2075 struct pending_cmd *cmd;
2076
2077 hci_dev_lock(hdev);
2078
2079 cmd = mgmt_pending_find(mgmt_op, hdev);
2080 if (!cmd)
2081 goto unlock;
2082
2083 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2084 hdev->dev_class, 3);
2085
2086 mgmt_pending_remove(cmd);
2087
2088unlock:
2089 hci_dev_unlock(hdev);
2090}
2091
2092static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2093{
2094 BT_DBG("status 0x%02x", status);
2095
2096 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2097}
2098
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002099static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002100{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002101 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002102 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002103 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002104 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002105 int err;
2106
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002107 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002108
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002109 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002110
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002111 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002112 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002113 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002114 goto failed;
2115 }
2116
Andre Guedes92c4c202012-06-07 19:05:44 -03002117 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002118 if (!uuid) {
2119 err = -ENOMEM;
2120 goto failed;
2121 }
2122
2123 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002124 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002125 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002126
Johan Hedbergde66aa62013-01-27 00:31:27 +02002127 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002128
Johan Hedberg890ea892013-03-15 17:06:52 -05002129 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002130
Johan Hedberg890ea892013-03-15 17:06:52 -05002131 update_class(&req);
2132 update_eir(&req);
2133
Johan Hedberg92da6092013-03-15 17:06:55 -05002134 err = hci_req_run(&req, add_uuid_complete);
2135 if (err < 0) {
2136 if (err != -ENODATA)
2137 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002138
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002139 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002140 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002141 goto failed;
2142 }
2143
2144 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002145 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002146 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002147 goto failed;
2148 }
2149
2150 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002151
2152failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002153 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002154 return err;
2155}
2156
Johan Hedberg24b78d02012-02-23 23:24:30 +02002157static bool enable_service_cache(struct hci_dev *hdev)
2158{
2159 if (!hdev_is_powered(hdev))
2160 return false;
2161
2162 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002163 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2164 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002165 return true;
2166 }
2167
2168 return false;
2169}
2170
Johan Hedberg92da6092013-03-15 17:06:55 -05002171static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2172{
2173 BT_DBG("status 0x%02x", status);
2174
2175 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2176}
2177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002178static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002179 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002180{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002181 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002182 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002183 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002184 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 -05002185 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002186 int err, found;
2187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002188 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002190 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002191
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002192 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002193 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002194 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002195 goto unlock;
2196 }
2197
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002198 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002199 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002200
Johan Hedberg24b78d02012-02-23 23:24:30 +02002201 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002202 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002203 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002204 goto unlock;
2205 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002206
Johan Hedberg9246a862012-02-23 21:33:16 +02002207 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002208 }
2209
2210 found = 0;
2211
Johan Hedberg056341c2013-01-27 00:31:30 +02002212 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002213 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2214 continue;
2215
2216 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002217 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002218 found++;
2219 }
2220
2221 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002222 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002223 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002224 goto unlock;
2225 }
2226
Johan Hedberg9246a862012-02-23 21:33:16 +02002227update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002228 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002229
Johan Hedberg890ea892013-03-15 17:06:52 -05002230 update_class(&req);
2231 update_eir(&req);
2232
Johan Hedberg92da6092013-03-15 17:06:55 -05002233 err = hci_req_run(&req, remove_uuid_complete);
2234 if (err < 0) {
2235 if (err != -ENODATA)
2236 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002239 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002240 goto unlock;
2241 }
2242
2243 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002244 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002245 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002246 goto unlock;
2247 }
2248
2249 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002250
2251unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002252 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253 return err;
2254}
2255
Johan Hedberg92da6092013-03-15 17:06:55 -05002256static void set_class_complete(struct hci_dev *hdev, u8 status)
2257{
2258 BT_DBG("status 0x%02x", status);
2259
2260 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2261}
2262
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002263static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002264 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002265{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002266 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002267 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002268 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002269 int err;
2270
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002271 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002272
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002273 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002274 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2275 MGMT_STATUS_NOT_SUPPORTED);
2276
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002277 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002278
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002279 if (pending_eir_or_class(hdev)) {
2280 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2281 MGMT_STATUS_BUSY);
2282 goto unlock;
2283 }
2284
2285 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2286 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2287 MGMT_STATUS_INVALID_PARAMS);
2288 goto unlock;
2289 }
2290
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002291 hdev->major_class = cp->major;
2292 hdev->minor_class = cp->minor;
2293
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002294 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002295 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002296 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002297 goto unlock;
2298 }
2299
Johan Hedberg890ea892013-03-15 17:06:52 -05002300 hci_req_init(&req, hdev);
2301
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002302 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002303 hci_dev_unlock(hdev);
2304 cancel_delayed_work_sync(&hdev->service_cache);
2305 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002306 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002307 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002308
Johan Hedberg890ea892013-03-15 17:06:52 -05002309 update_class(&req);
2310
Johan Hedberg92da6092013-03-15 17:06:55 -05002311 err = hci_req_run(&req, set_class_complete);
2312 if (err < 0) {
2313 if (err != -ENODATA)
2314 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002316 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002317 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002318 goto unlock;
2319 }
2320
2321 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002322 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002323 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002324 goto unlock;
2325 }
2326
2327 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002328
Johan Hedbergb5235a62012-02-21 14:32:24 +02002329unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002330 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331 return err;
2332}
2333
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002334static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002335 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002336{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002337 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002338 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002339 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002340 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002341
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002342 BT_DBG("request for %s", hdev->name);
2343
2344 if (!lmp_bredr_capable(hdev))
2345 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2346 MGMT_STATUS_NOT_SUPPORTED);
2347
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002348 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002349
Johan Hedberg86742e12011-11-07 23:13:38 +02002350 expected_len = sizeof(*cp) + key_count *
2351 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002352 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002353 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002354 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002355 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002356 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002357 }
2358
Johan Hedberg4ae14302013-01-20 14:27:13 +02002359 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2360 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2361 MGMT_STATUS_INVALID_PARAMS);
2362
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002363 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002364 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002365
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002366 for (i = 0; i < key_count; i++) {
2367 struct mgmt_link_key_info *key = &cp->keys[i];
2368
Marcel Holtmann8e991132014-01-10 02:07:25 -08002369 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002370 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2371 MGMT_STATUS_INVALID_PARAMS);
2372 }
2373
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002374 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002375
2376 hci_link_keys_clear(hdev);
2377
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002378 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002379 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002380 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002381 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2382
2383 if (changed)
2384 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002385
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002386 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002387 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002388
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002389 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002390 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002391 }
2392
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002394
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002395 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002396
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002397 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002398}
2399
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002400static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002401 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002402{
2403 struct mgmt_ev_device_unpaired ev;
2404
2405 bacpy(&ev.addr.bdaddr, bdaddr);
2406 ev.addr.type = addr_type;
2407
2408 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002410}
2411
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002412static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002413 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002414{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002415 struct mgmt_cp_unpair_device *cp = data;
2416 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002417 struct hci_cp_disconnect dc;
2418 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002419 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002420 int err;
2421
Johan Hedberga8a1d192011-11-10 15:54:38 +02002422 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002423 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2424 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002425
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002426 if (!bdaddr_type_is_valid(cp->addr.type))
2427 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2428 MGMT_STATUS_INVALID_PARAMS,
2429 &rp, sizeof(rp));
2430
Johan Hedberg118da702013-01-20 14:27:20 +02002431 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2432 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2433 MGMT_STATUS_INVALID_PARAMS,
2434 &rp, sizeof(rp));
2435
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002436 hci_dev_lock(hdev);
2437
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002438 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002439 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002440 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002441 goto unlock;
2442 }
2443
Johan Hedberge0b2b272014-02-18 17:14:31 +02002444 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002445 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002446 } else {
2447 u8 addr_type;
2448
2449 if (cp->addr.type == BDADDR_LE_PUBLIC)
2450 addr_type = ADDR_LE_DEV_PUBLIC;
2451 else
2452 addr_type = ADDR_LE_DEV_RANDOM;
2453
Johan Hedberga7ec7332014-02-18 17:14:35 +02002454 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2455
Andre Guedesa9b0a042014-02-26 20:21:52 -03002456 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2457
Johan Hedberge0b2b272014-02-18 17:14:31 +02002458 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2459 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002460
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002461 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002462 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002463 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002464 goto unlock;
2465 }
2466
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002467 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002468 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002469 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002470 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002471 else
2472 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002473 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002474 } else {
2475 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002476 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002477
Johan Hedberga8a1d192011-11-10 15:54:38 +02002478 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002479 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002480 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002481 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002482 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002483 }
2484
Johan Hedberg124f6e32012-02-09 13:50:12 +02002485 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002486 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002487 if (!cmd) {
2488 err = -ENOMEM;
2489 goto unlock;
2490 }
2491
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002492 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002493 dc.reason = 0x13; /* Remote User Terminated Connection */
2494 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2495 if (err < 0)
2496 mgmt_pending_remove(cmd);
2497
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002498unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002499 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002500 return err;
2501}
2502
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002503static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002504 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002505{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002506 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002507 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002508 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002509 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002510 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002511 int err;
2512
2513 BT_DBG("");
2514
Johan Hedberg06a63b12013-01-20 14:27:21 +02002515 memset(&rp, 0, sizeof(rp));
2516 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2517 rp.addr.type = cp->addr.type;
2518
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002519 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002520 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2521 MGMT_STATUS_INVALID_PARAMS,
2522 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002523
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002524 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002525
2526 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002527 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2528 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002529 goto failed;
2530 }
2531
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002532 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002533 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2534 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002535 goto failed;
2536 }
2537
Andre Guedes591f47f2012-04-24 21:02:49 -03002538 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002539 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2540 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002541 else
2542 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002543
Vishal Agarwalf9607272012-06-13 05:32:43 +05302544 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002545 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2546 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002547 goto failed;
2548 }
2549
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002550 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002551 if (!cmd) {
2552 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002553 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002554 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002555
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002556 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002557 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002558
2559 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2560 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002561 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002562
2563failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002564 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002565 return err;
2566}
2567
Andre Guedes57c14772012-04-24 21:02:50 -03002568static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002569{
2570 switch (link_type) {
2571 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002572 switch (addr_type) {
2573 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002574 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002575
Johan Hedberg48264f02011-11-09 13:58:58 +02002576 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002577 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002578 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002579 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002580
Johan Hedberg4c659c32011-11-07 23:13:39 +02002581 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002582 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002583 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002584 }
2585}
2586
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002587static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2588 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002589{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002590 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002591 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002592 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002593 int err;
2594 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002595
2596 BT_DBG("");
2597
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002598 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002599
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002600 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002601 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002602 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002603 goto unlock;
2604 }
2605
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002606 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002607 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2608 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002609 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002610 }
2611
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002612 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002613 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002614 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002615 err = -ENOMEM;
2616 goto unlock;
2617 }
2618
Johan Hedberg2784eb42011-01-21 13:56:35 +02002619 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002620 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002621 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2622 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002623 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002624 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002625 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002626 continue;
2627 i++;
2628 }
2629
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002630 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002631
Johan Hedberg4c659c32011-11-07 23:13:39 +02002632 /* Recalculate length in case of filtered SCO connections, etc */
2633 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002634
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002635 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002636 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002637
Johan Hedberga38528f2011-01-22 06:46:43 +02002638 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002639
2640unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002641 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002642 return err;
2643}
2644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002645static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002646 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002647{
2648 struct pending_cmd *cmd;
2649 int err;
2650
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002651 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002652 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002653 if (!cmd)
2654 return -ENOMEM;
2655
Johan Hedbergd8457692012-02-17 14:24:57 +02002656 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002657 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002658 if (err < 0)
2659 mgmt_pending_remove(cmd);
2660
2661 return err;
2662}
2663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002664static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002665 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002666{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002667 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002668 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002669 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002670 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002671 int err;
2672
2673 BT_DBG("");
2674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002675 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002676
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002677 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002678 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002679 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002680 goto failed;
2681 }
2682
Johan Hedbergd8457692012-02-17 14:24:57 +02002683 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002684 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002685 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002686 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002687 goto failed;
2688 }
2689
2690 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002691 struct mgmt_cp_pin_code_neg_reply ncp;
2692
2693 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002694
2695 BT_ERR("PIN code is not 16 bytes long");
2696
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002697 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002698 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002699 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002700 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002701
2702 goto failed;
2703 }
2704
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002705 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002706 if (!cmd) {
2707 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002708 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002709 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002710
Johan Hedbergd8457692012-02-17 14:24:57 +02002711 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002712 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002713 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002714
2715 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2716 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002717 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002718
2719failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002720 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002721 return err;
2722}
2723
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002724static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2725 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002726{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002727 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002728
2729 BT_DBG("");
2730
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002731 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002732
2733 hdev->io_capability = cp->io_capability;
2734
2735 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002736 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002737
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002738 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002739
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002740 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2741 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002742}
2743
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002744static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002745{
2746 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002747 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002748
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002749 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002750 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2751 continue;
2752
Johan Hedberge9a416b2011-02-19 12:05:56 -03002753 if (cmd->user_data != conn)
2754 continue;
2755
2756 return cmd;
2757 }
2758
2759 return NULL;
2760}
2761
2762static void pairing_complete(struct pending_cmd *cmd, u8 status)
2763{
2764 struct mgmt_rp_pair_device rp;
2765 struct hci_conn *conn = cmd->user_data;
2766
Johan Hedbergba4e5642011-11-11 00:07:34 +02002767 bacpy(&rp.addr.bdaddr, &conn->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002768 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002769
Johan Hedbergaee9b212012-02-18 15:07:59 +02002770 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002771 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002772
2773 /* So we don't get further callbacks for this connection */
2774 conn->connect_cfm_cb = NULL;
2775 conn->security_cfm_cb = NULL;
2776 conn->disconn_cfm_cb = NULL;
2777
David Herrmann76a68ba2013-04-06 20:28:37 +02002778 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002779
Johan Hedberga664b5b2011-02-19 12:06:02 -03002780 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002781}
2782
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002783void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2784{
2785 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2786 struct pending_cmd *cmd;
2787
2788 cmd = find_pairing(conn);
2789 if (cmd)
2790 pairing_complete(cmd, status);
2791}
2792
Johan Hedberge9a416b2011-02-19 12:05:56 -03002793static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2794{
2795 struct pending_cmd *cmd;
2796
2797 BT_DBG("status %u", status);
2798
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002799 cmd = find_pairing(conn);
2800 if (!cmd)
2801 BT_DBG("Unable to find a pending command");
2802 else
Johan Hedberge2113262012-02-18 15:20:03 +02002803 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002804}
2805
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002806static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302807{
2808 struct pending_cmd *cmd;
2809
2810 BT_DBG("status %u", status);
2811
2812 if (!status)
2813 return;
2814
2815 cmd = find_pairing(conn);
2816 if (!cmd)
2817 BT_DBG("Unable to find a pending command");
2818 else
2819 pairing_complete(cmd, mgmt_status(status));
2820}
2821
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002822static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002823 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002824{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002825 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002826 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002827 struct pending_cmd *cmd;
2828 u8 sec_level, auth_type;
2829 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002830 int err;
2831
2832 BT_DBG("");
2833
Szymon Jancf950a30e2013-01-18 12:48:07 +01002834 memset(&rp, 0, sizeof(rp));
2835 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2836 rp.addr.type = cp->addr.type;
2837
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002838 if (!bdaddr_type_is_valid(cp->addr.type))
2839 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2840 MGMT_STATUS_INVALID_PARAMS,
2841 &rp, sizeof(rp));
2842
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002843 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002844
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002845 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002846 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2847 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002848 goto unlock;
2849 }
2850
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002851 sec_level = BT_SECURITY_MEDIUM;
2852 if (cp->io_cap == 0x03)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002853 auth_type = HCI_AT_DEDICATED_BONDING;
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002854 else
Johan Hedberge9a416b2011-02-19 12:05:56 -03002855 auth_type = HCI_AT_DEDICATED_BONDING_MITM;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002856
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002857 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002858 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2859 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002860 } else {
2861 u8 addr_type;
2862
2863 /* Convert from L2CAP channel address type to HCI address type
2864 */
2865 if (cp->addr.type == BDADDR_LE_PUBLIC)
2866 addr_type = ADDR_LE_DEV_PUBLIC;
2867 else
2868 addr_type = ADDR_LE_DEV_RANDOM;
2869
2870 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002871 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002872 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002873
Ville Tervo30e76272011-02-22 16:10:53 -03002874 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002875 int status;
2876
2877 if (PTR_ERR(conn) == -EBUSY)
2878 status = MGMT_STATUS_BUSY;
2879 else
2880 status = MGMT_STATUS_CONNECT_FAILED;
2881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002882 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002883 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002884 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002885 goto unlock;
2886 }
2887
2888 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002889 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002890 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002891 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002892 goto unlock;
2893 }
2894
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002895 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002896 if (!cmd) {
2897 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002898 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002899 goto unlock;
2900 }
2901
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002902 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002903 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002904 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002905 conn->security_cfm_cb = pairing_complete_cb;
2906 conn->disconn_cfm_cb = pairing_complete_cb;
2907 } else {
2908 conn->connect_cfm_cb = le_pairing_complete_cb;
2909 conn->security_cfm_cb = le_pairing_complete_cb;
2910 conn->disconn_cfm_cb = le_pairing_complete_cb;
2911 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002912
Johan Hedberge9a416b2011-02-19 12:05:56 -03002913 conn->io_capability = cp->io_cap;
2914 cmd->user_data = conn;
2915
2916 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002917 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002918 pairing_complete(cmd, 0);
2919
2920 err = 0;
2921
2922unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002923 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002924 return err;
2925}
2926
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002927static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2928 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002929{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002930 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002931 struct pending_cmd *cmd;
2932 struct hci_conn *conn;
2933 int err;
2934
2935 BT_DBG("");
2936
Johan Hedberg28424702012-02-02 04:02:29 +02002937 hci_dev_lock(hdev);
2938
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002939 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002940 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002941 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002942 goto unlock;
2943 }
2944
Johan Hedberg28424702012-02-02 04:02:29 +02002945 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2946 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002947 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002948 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002949 goto unlock;
2950 }
2951
2952 conn = cmd->user_data;
2953
2954 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002955 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002956 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002957 goto unlock;
2958 }
2959
2960 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2961
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002962 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002963 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002964unlock:
2965 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002966 return err;
2967}
2968
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002969static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002970 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002971 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002972{
Johan Hedberga5c29682011-02-19 12:05:57 -03002973 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002974 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002975 int err;
2976
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002977 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002978
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002979 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002980 err = cmd_complete(sk, hdev->id, mgmt_op,
2981 MGMT_STATUS_NOT_POWERED, addr,
2982 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002983 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002984 }
2985
Johan Hedberg1707c602013-03-15 17:07:15 -05002986 if (addr->type == BDADDR_BREDR)
2987 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002988 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002989 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002990
Johan Hedberg272d90d2012-02-09 15:26:12 +02002991 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002992 err = cmd_complete(sk, hdev->id, mgmt_op,
2993 MGMT_STATUS_NOT_CONNECTED, addr,
2994 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002995 goto done;
2996 }
2997
Johan Hedberg1707c602013-03-15 17:07:15 -05002998 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002999 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08003000 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08003001
Brian Gix5fe57d92011-12-21 16:12:13 -08003002 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003003 err = cmd_complete(sk, hdev->id, mgmt_op,
3004 MGMT_STATUS_SUCCESS, addr,
3005 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003006 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003007 err = cmd_complete(sk, hdev->id, mgmt_op,
3008 MGMT_STATUS_FAILED, addr,
3009 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003010
Brian Gix47c15e22011-11-16 13:53:14 -08003011 goto done;
3012 }
3013
Johan Hedberg1707c602013-03-15 17:07:15 -05003014 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003015 if (!cmd) {
3016 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003017 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003018 }
3019
Brian Gix0df4c182011-11-16 13:53:13 -08003020 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003021 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3022 struct hci_cp_user_passkey_reply cp;
3023
Johan Hedberg1707c602013-03-15 17:07:15 -05003024 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003025 cp.passkey = passkey;
3026 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3027 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003028 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3029 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003030
Johan Hedberga664b5b2011-02-19 12:06:02 -03003031 if (err < 0)
3032 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003033
Brian Gix0df4c182011-11-16 13:53:13 -08003034done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003035 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003036 return err;
3037}
3038
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303039static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3040 void *data, u16 len)
3041{
3042 struct mgmt_cp_pin_code_neg_reply *cp = data;
3043
3044 BT_DBG("");
3045
Johan Hedberg1707c602013-03-15 17:07:15 -05003046 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303047 MGMT_OP_PIN_CODE_NEG_REPLY,
3048 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3049}
3050
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003051static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3052 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003053{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003054 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003055
3056 BT_DBG("");
3057
3058 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003059 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003061
Johan Hedberg1707c602013-03-15 17:07:15 -05003062 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003063 MGMT_OP_USER_CONFIRM_REPLY,
3064 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003065}
3066
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003067static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003068 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003069{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003070 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003071
3072 BT_DBG("");
3073
Johan Hedberg1707c602013-03-15 17:07:15 -05003074 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003075 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3076 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003077}
3078
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3080 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003081{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003082 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003083
3084 BT_DBG("");
3085
Johan Hedberg1707c602013-03-15 17:07:15 -05003086 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003087 MGMT_OP_USER_PASSKEY_REPLY,
3088 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003089}
3090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003091static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003092 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003093{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003094 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003095
3096 BT_DBG("");
3097
Johan Hedberg1707c602013-03-15 17:07:15 -05003098 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003099 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3100 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003101}
3102
Johan Hedberg13928972013-03-15 17:07:00 -05003103static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003104{
Johan Hedberg13928972013-03-15 17:07:00 -05003105 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003106 struct hci_cp_write_local_name cp;
3107
Johan Hedberg13928972013-03-15 17:07:00 -05003108 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003109
Johan Hedberg890ea892013-03-15 17:06:52 -05003110 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003111}
3112
Johan Hedberg13928972013-03-15 17:07:00 -05003113static void set_name_complete(struct hci_dev *hdev, u8 status)
3114{
3115 struct mgmt_cp_set_local_name *cp;
3116 struct pending_cmd *cmd;
3117
3118 BT_DBG("status 0x%02x", status);
3119
3120 hci_dev_lock(hdev);
3121
3122 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3123 if (!cmd)
3124 goto unlock;
3125
3126 cp = cmd->param;
3127
3128 if (status)
3129 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3130 mgmt_status(status));
3131 else
3132 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3133 cp, sizeof(*cp));
3134
3135 mgmt_pending_remove(cmd);
3136
3137unlock:
3138 hci_dev_unlock(hdev);
3139}
3140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003141static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003142 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003143{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003144 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003145 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003146 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003147 int err;
3148
3149 BT_DBG("");
3150
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003151 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003152
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003153 /* If the old values are the same as the new ones just return a
3154 * direct command complete event.
3155 */
3156 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3157 !memcmp(hdev->short_name, cp->short_name,
3158 sizeof(hdev->short_name))) {
3159 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3160 data, len);
3161 goto failed;
3162 }
3163
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003164 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003165
Johan Hedbergb5235a62012-02-21 14:32:24 +02003166 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003167 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003168
3169 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003171 if (err < 0)
3172 goto failed;
3173
3174 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003176
Johan Hedbergb5235a62012-02-21 14:32:24 +02003177 goto failed;
3178 }
3179
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003180 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003181 if (!cmd) {
3182 err = -ENOMEM;
3183 goto failed;
3184 }
3185
Johan Hedberg13928972013-03-15 17:07:00 -05003186 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3187
Johan Hedberg890ea892013-03-15 17:06:52 -05003188 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003189
3190 if (lmp_bredr_capable(hdev)) {
3191 update_name(&req);
3192 update_eir(&req);
3193 }
3194
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003195 /* The name is stored in the scan response data and so
3196 * no need to udpate the advertising data here.
3197 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003198 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003199 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003200
Johan Hedberg13928972013-03-15 17:07:00 -05003201 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003202 if (err < 0)
3203 mgmt_pending_remove(cmd);
3204
3205failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003206 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003207 return err;
3208}
3209
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003210static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003211 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003212{
Szymon Jancc35938b2011-03-22 13:12:21 +01003213 struct pending_cmd *cmd;
3214 int err;
3215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003216 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003217
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003218 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003219
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003220 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003221 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003222 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003223 goto unlock;
3224 }
3225
Andre Guedes9a1a1992012-07-24 15:03:48 -03003226 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003227 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003228 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003229 goto unlock;
3230 }
3231
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003232 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003233 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003234 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003235 goto unlock;
3236 }
3237
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003238 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003239 if (!cmd) {
3240 err = -ENOMEM;
3241 goto unlock;
3242 }
3243
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003244 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3245 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3246 0, NULL);
3247 else
3248 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3249
Szymon Jancc35938b2011-03-22 13:12:21 +01003250 if (err < 0)
3251 mgmt_pending_remove(cmd);
3252
3253unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003254 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003255 return err;
3256}
3257
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003260{
Szymon Janc2763eda2011-03-22 13:12:22 +01003261 int err;
3262
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003263 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003265 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003266
Marcel Holtmannec109112014-01-10 02:07:30 -08003267 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3268 struct mgmt_cp_add_remote_oob_data *cp = data;
3269 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003270
Marcel Holtmannec109112014-01-10 02:07:30 -08003271 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3272 cp->hash, cp->randomizer);
3273 if (err < 0)
3274 status = MGMT_STATUS_FAILED;
3275 else
3276 status = MGMT_STATUS_SUCCESS;
3277
3278 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3279 status, &cp->addr, sizeof(cp->addr));
3280 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3281 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3282 u8 status;
3283
3284 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3285 cp->hash192,
3286 cp->randomizer192,
3287 cp->hash256,
3288 cp->randomizer256);
3289 if (err < 0)
3290 status = MGMT_STATUS_FAILED;
3291 else
3292 status = MGMT_STATUS_SUCCESS;
3293
3294 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3295 status, &cp->addr, sizeof(cp->addr));
3296 } else {
3297 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3298 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3299 MGMT_STATUS_INVALID_PARAMS);
3300 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003302 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003303 return err;
3304}
3305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003306static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003307 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003308{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003309 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003310 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003311 int err;
3312
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003314
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003315 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003316
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003317 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003318 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003319 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003320 else
Szymon Janca6785be2012-12-13 15:11:21 +01003321 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003323 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003325
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003326 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003327 return err;
3328}
3329
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003330static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3331{
3332 struct pending_cmd *cmd;
3333 u8 type;
3334 int err;
3335
3336 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3337
3338 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3339 if (!cmd)
3340 return -ENOENT;
3341
3342 type = hdev->discovery.type;
3343
3344 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3345 &type, sizeof(type));
3346 mgmt_pending_remove(cmd);
3347
3348 return err;
3349}
3350
Andre Guedes7c307722013-04-30 15:29:28 -03003351static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3352{
3353 BT_DBG("status %d", status);
3354
3355 if (status) {
3356 hci_dev_lock(hdev);
3357 mgmt_start_discovery_failed(hdev, status);
3358 hci_dev_unlock(hdev);
3359 return;
3360 }
3361
3362 hci_dev_lock(hdev);
3363 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3364 hci_dev_unlock(hdev);
3365
3366 switch (hdev->discovery.type) {
3367 case DISCOV_TYPE_LE:
3368 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003369 DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003370 break;
3371
3372 case DISCOV_TYPE_INTERLEAVED:
3373 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable,
Andre Guedes0d8cc932013-04-30 15:29:31 -03003374 DISCOV_INTERLEAVED_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003375 break;
3376
3377 case DISCOV_TYPE_BREDR:
3378 break;
3379
3380 default:
3381 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3382 }
3383}
3384
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003385static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003386 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003387{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003388 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003389 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003390 struct hci_cp_le_set_scan_param param_cp;
3391 struct hci_cp_le_set_scan_enable enable_cp;
3392 struct hci_cp_inquiry inq_cp;
3393 struct hci_request req;
3394 /* General inquiry access code (GIAC) */
3395 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003396 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003397 int err;
3398
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003399 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003400
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003401 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003402
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003403 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003404 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003405 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003406 goto failed;
3407 }
3408
Andre Guedes642be6c2012-03-21 00:03:37 -03003409 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3410 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3411 MGMT_STATUS_BUSY);
3412 goto failed;
3413 }
3414
Johan Hedbergff9ef572012-01-04 14:23:45 +02003415 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003416 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003417 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003418 goto failed;
3419 }
3420
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003421 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003422 if (!cmd) {
3423 err = -ENOMEM;
3424 goto failed;
3425 }
3426
Andre Guedes4aab14e2012-02-17 20:39:36 -03003427 hdev->discovery.type = cp->type;
3428
Andre Guedes7c307722013-04-30 15:29:28 -03003429 hci_req_init(&req, hdev);
3430
Andre Guedes4aab14e2012-02-17 20:39:36 -03003431 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003432 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003433 status = mgmt_bredr_support(hdev);
3434 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003435 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003436 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003437 mgmt_pending_remove(cmd);
3438 goto failed;
3439 }
3440
Andre Guedes7c307722013-04-30 15:29:28 -03003441 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3442 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3443 MGMT_STATUS_BUSY);
3444 mgmt_pending_remove(cmd);
3445 goto failed;
3446 }
3447
3448 hci_inquiry_cache_flush(hdev);
3449
3450 memset(&inq_cp, 0, sizeof(inq_cp));
3451 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003452 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003453 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003454 break;
3455
3456 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003457 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003458 status = mgmt_le_support(hdev);
3459 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003460 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003461 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003462 mgmt_pending_remove(cmd);
3463 goto failed;
3464 }
3465
Andre Guedes7c307722013-04-30 15:29:28 -03003466 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003467 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003468 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3469 MGMT_STATUS_NOT_SUPPORTED);
3470 mgmt_pending_remove(cmd);
3471 goto failed;
3472 }
3473
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003474 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003475 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3476 MGMT_STATUS_REJECTED);
3477 mgmt_pending_remove(cmd);
3478 goto failed;
3479 }
3480
Andre Guedesc54c3862014-02-26 20:21:50 -03003481 /* If controller is scanning, it means the background scanning
3482 * is running. Thus, we should temporarily stop it in order to
3483 * set the discovery scanning parameters.
3484 */
3485 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3486 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003487
3488 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003489
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003490 /* All active scans will be done with either a resolvable
3491 * private address (when privacy feature has been enabled)
3492 * or unresolvable private address.
3493 */
3494 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003495 if (err < 0) {
3496 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3497 MGMT_STATUS_FAILED);
3498 mgmt_pending_remove(cmd);
3499 goto failed;
3500 }
3501
Andre Guedes7c307722013-04-30 15:29:28 -03003502 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003503 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3504 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003505 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003506 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3507 &param_cp);
3508
3509 memset(&enable_cp, 0, sizeof(enable_cp));
3510 enable_cp.enable = LE_SCAN_ENABLE;
3511 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3512 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3513 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003514 break;
3515
Andre Guedesf39799f2012-02-17 20:39:35 -03003516 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003517 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3518 MGMT_STATUS_INVALID_PARAMS);
3519 mgmt_pending_remove(cmd);
3520 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003521 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003522
Andre Guedes7c307722013-04-30 15:29:28 -03003523 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003524 if (err < 0)
3525 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003526 else
3527 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003528
3529failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003530 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003531 return err;
3532}
3533
Andre Guedes1183fdc2013-04-30 15:29:35 -03003534static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3535{
3536 struct pending_cmd *cmd;
3537 int err;
3538
3539 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3540 if (!cmd)
3541 return -ENOENT;
3542
3543 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3544 &hdev->discovery.type, sizeof(hdev->discovery.type));
3545 mgmt_pending_remove(cmd);
3546
3547 return err;
3548}
3549
Andre Guedes0e05bba2013-04-30 15:29:33 -03003550static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3551{
3552 BT_DBG("status %d", status);
3553
3554 hci_dev_lock(hdev);
3555
3556 if (status) {
3557 mgmt_stop_discovery_failed(hdev, status);
3558 goto unlock;
3559 }
3560
3561 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3562
3563unlock:
3564 hci_dev_unlock(hdev);
3565}
3566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003567static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003568 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003569{
Johan Hedbergd9306502012-02-20 23:25:18 +02003570 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003571 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003572 struct hci_cp_remote_name_req_cancel cp;
3573 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003574 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003575 int err;
3576
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003577 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003578
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003579 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003580
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003581 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003582 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3584 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003585 goto unlock;
3586 }
3587
3588 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003589 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003590 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3591 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003592 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003593 }
3594
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003595 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003596 if (!cmd) {
3597 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003598 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003599 }
3600
Andre Guedes0e05bba2013-04-30 15:29:33 -03003601 hci_req_init(&req, hdev);
3602
Andre Guedese0d9727e2012-03-20 15:15:36 -03003603 switch (hdev->discovery.state) {
3604 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003605 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3606 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3607 } else {
3608 cancel_delayed_work(&hdev->le_scan_disable);
3609
Andre Guedesb1efcc22014-02-26 20:21:40 -03003610 hci_req_add_le_scan_disable(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003611 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003612
Andre Guedese0d9727e2012-03-20 15:15:36 -03003613 break;
3614
3615 case DISCOVERY_RESOLVING:
3616 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003617 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003618 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003619 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003620 err = cmd_complete(sk, hdev->id,
3621 MGMT_OP_STOP_DISCOVERY, 0,
3622 &mgmt_cp->type,
3623 sizeof(mgmt_cp->type));
3624 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3625 goto unlock;
3626 }
3627
3628 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003629 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3630 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003631
3632 break;
3633
3634 default:
3635 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003636
3637 mgmt_pending_remove(cmd);
3638 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3639 MGMT_STATUS_FAILED, &mgmt_cp->type,
3640 sizeof(mgmt_cp->type));
3641 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003642 }
3643
Andre Guedes0e05bba2013-04-30 15:29:33 -03003644 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003645 if (err < 0)
3646 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003647 else
3648 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003649
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003650unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003651 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003652 return err;
3653}
3654
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003655static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003656 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003657{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003658 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003659 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003660 int err;
3661
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003662 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003663
Johan Hedberg561aafb2012-01-04 13:31:59 +02003664 hci_dev_lock(hdev);
3665
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003666 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003667 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3668 MGMT_STATUS_FAILED, &cp->addr,
3669 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003670 goto failed;
3671 }
3672
Johan Hedberga198e7b2012-02-17 14:27:06 +02003673 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003674 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003675 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3676 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3677 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003678 goto failed;
3679 }
3680
3681 if (cp->name_known) {
3682 e->name_state = NAME_KNOWN;
3683 list_del(&e->list);
3684 } else {
3685 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003686 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003687 }
3688
Johan Hedberge3846622013-01-09 15:29:33 +02003689 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3690 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003691
3692failed:
3693 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003694 return err;
3695}
3696
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003697static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003698 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003699{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003700 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003701 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003702 int err;
3703
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003704 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003705
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003706 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003707 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3708 MGMT_STATUS_INVALID_PARAMS,
3709 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003710
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003711 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003712
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003713 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003714 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003715 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003716 else
Szymon Janca6785be2012-12-13 15:11:21 +01003717 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003718
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003719 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003720 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003721
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003722 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003723
3724 return err;
3725}
3726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003727static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003728 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003729{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003730 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003731 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003732 int err;
3733
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003734 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003735
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003736 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003737 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3738 MGMT_STATUS_INVALID_PARAMS,
3739 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003741 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003742
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003743 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003744 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003745 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003746 else
Szymon Janca6785be2012-12-13 15:11:21 +01003747 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003748
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003749 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003750 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003752 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003753
3754 return err;
3755}
3756
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003757static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3758 u16 len)
3759{
3760 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003761 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003762 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003763 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003764
3765 BT_DBG("%s", hdev->name);
3766
Szymon Jancc72d4b82012-03-16 16:02:57 +01003767 source = __le16_to_cpu(cp->source);
3768
3769 if (source > 0x0002)
3770 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3771 MGMT_STATUS_INVALID_PARAMS);
3772
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003773 hci_dev_lock(hdev);
3774
Szymon Jancc72d4b82012-03-16 16:02:57 +01003775 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003776 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3777 hdev->devid_product = __le16_to_cpu(cp->product);
3778 hdev->devid_version = __le16_to_cpu(cp->version);
3779
3780 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3781
Johan Hedberg890ea892013-03-15 17:06:52 -05003782 hci_req_init(&req, hdev);
3783 update_eir(&req);
3784 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003785
3786 hci_dev_unlock(hdev);
3787
3788 return err;
3789}
3790
Johan Hedberg4375f102013-09-25 13:26:10 +03003791static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3792{
3793 struct cmd_lookup match = { NULL, hdev };
3794
3795 if (status) {
3796 u8 mgmt_err = mgmt_status(status);
3797
3798 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3799 cmd_status_rsp, &mgmt_err);
3800 return;
3801 }
3802
3803 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3804 &match);
3805
3806 new_settings(hdev, match.sk);
3807
3808 if (match.sk)
3809 sock_put(match.sk);
3810}
3811
Marcel Holtmann21b51872013-10-10 09:47:53 -07003812static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3813 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003814{
3815 struct mgmt_mode *cp = data;
3816 struct pending_cmd *cmd;
3817 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003818 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003819 int err;
3820
3821 BT_DBG("request for %s", hdev->name);
3822
Johan Hedberge6fe7982013-10-02 15:45:22 +03003823 status = mgmt_le_support(hdev);
3824 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003825 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003826 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003827
3828 if (cp->val != 0x00 && cp->val != 0x01)
3829 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3830 MGMT_STATUS_INVALID_PARAMS);
3831
3832 hci_dev_lock(hdev);
3833
3834 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003835 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003836
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003837 /* The following conditions are ones which mean that we should
3838 * not do any HCI communication but directly send a mgmt
3839 * response to user space (after toggling the flag if
3840 * necessary).
3841 */
3842 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003843 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003844 bool changed = false;
3845
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003846 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3847 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003848 changed = true;
3849 }
3850
3851 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3852 if (err < 0)
3853 goto unlock;
3854
3855 if (changed)
3856 err = new_settings(hdev, sk);
3857
3858 goto unlock;
3859 }
3860
3861 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3862 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3863 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3864 MGMT_STATUS_BUSY);
3865 goto unlock;
3866 }
3867
3868 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3869 if (!cmd) {
3870 err = -ENOMEM;
3871 goto unlock;
3872 }
3873
3874 hci_req_init(&req, hdev);
3875
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003876 if (val)
3877 enable_advertising(&req);
3878 else
3879 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003880
3881 err = hci_req_run(&req, set_advertising_complete);
3882 if (err < 0)
3883 mgmt_pending_remove(cmd);
3884
3885unlock:
3886 hci_dev_unlock(hdev);
3887 return err;
3888}
3889
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003890static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3891 void *data, u16 len)
3892{
3893 struct mgmt_cp_set_static_address *cp = data;
3894 int err;
3895
3896 BT_DBG("%s", hdev->name);
3897
Marcel Holtmann62af4442013-10-02 22:10:32 -07003898 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003899 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003900 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003901
3902 if (hdev_is_powered(hdev))
3903 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3904 MGMT_STATUS_REJECTED);
3905
3906 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3907 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3908 return cmd_status(sk, hdev->id,
3909 MGMT_OP_SET_STATIC_ADDRESS,
3910 MGMT_STATUS_INVALID_PARAMS);
3911
3912 /* Two most significant bits shall be set */
3913 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3914 return cmd_status(sk, hdev->id,
3915 MGMT_OP_SET_STATIC_ADDRESS,
3916 MGMT_STATUS_INVALID_PARAMS);
3917 }
3918
3919 hci_dev_lock(hdev);
3920
3921 bacpy(&hdev->static_addr, &cp->bdaddr);
3922
3923 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3924
3925 hci_dev_unlock(hdev);
3926
3927 return err;
3928}
3929
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003930static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3931 void *data, u16 len)
3932{
3933 struct mgmt_cp_set_scan_params *cp = data;
3934 __u16 interval, window;
3935 int err;
3936
3937 BT_DBG("%s", hdev->name);
3938
3939 if (!lmp_le_capable(hdev))
3940 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3941 MGMT_STATUS_NOT_SUPPORTED);
3942
3943 interval = __le16_to_cpu(cp->interval);
3944
3945 if (interval < 0x0004 || interval > 0x4000)
3946 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3947 MGMT_STATUS_INVALID_PARAMS);
3948
3949 window = __le16_to_cpu(cp->window);
3950
3951 if (window < 0x0004 || window > 0x4000)
3952 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3953 MGMT_STATUS_INVALID_PARAMS);
3954
Marcel Holtmann899e1072013-10-14 09:55:32 -07003955 if (window > interval)
3956 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3957 MGMT_STATUS_INVALID_PARAMS);
3958
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003959 hci_dev_lock(hdev);
3960
3961 hdev->le_scan_interval = interval;
3962 hdev->le_scan_window = window;
3963
3964 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3965
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003966 /* If background scan is running, restart it so new parameters are
3967 * loaded.
3968 */
3969 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3970 hdev->discovery.state == DISCOVERY_STOPPED) {
3971 struct hci_request req;
3972
3973 hci_req_init(&req, hdev);
3974
3975 hci_req_add_le_scan_disable(&req);
3976 hci_req_add_le_passive_scan(&req);
3977
3978 hci_req_run(&req, NULL);
3979 }
3980
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003981 hci_dev_unlock(hdev);
3982
3983 return err;
3984}
3985
Johan Hedberg33e38b32013-03-15 17:07:05 -05003986static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3987{
3988 struct pending_cmd *cmd;
3989
3990 BT_DBG("status 0x%02x", status);
3991
3992 hci_dev_lock(hdev);
3993
3994 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3995 if (!cmd)
3996 goto unlock;
3997
3998 if (status) {
3999 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4000 mgmt_status(status));
4001 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004002 struct mgmt_mode *cp = cmd->param;
4003
4004 if (cp->val)
4005 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4006 else
4007 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4008
Johan Hedberg33e38b32013-03-15 17:07:05 -05004009 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4010 new_settings(hdev, cmd->sk);
4011 }
4012
4013 mgmt_pending_remove(cmd);
4014
4015unlock:
4016 hci_dev_unlock(hdev);
4017}
4018
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004019static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004020 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004021{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004022 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004023 struct pending_cmd *cmd;
4024 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004025 int err;
4026
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004027 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004028
Johan Hedberg56f87902013-10-02 13:43:13 +03004029 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4030 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004031 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4032 MGMT_STATUS_NOT_SUPPORTED);
4033
Johan Hedberga7e80f22013-01-09 16:05:19 +02004034 if (cp->val != 0x00 && cp->val != 0x01)
4035 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4036 MGMT_STATUS_INVALID_PARAMS);
4037
Johan Hedberg5400c042012-02-21 16:40:33 +02004038 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004039 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004040 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004041
4042 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004043 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004044 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004045
4046 hci_dev_lock(hdev);
4047
Johan Hedberg05cbf292013-03-15 17:07:07 -05004048 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4049 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4050 MGMT_STATUS_BUSY);
4051 goto unlock;
4052 }
4053
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004054 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4055 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4056 hdev);
4057 goto unlock;
4058 }
4059
Johan Hedberg33e38b32013-03-15 17:07:05 -05004060 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4061 data, len);
4062 if (!cmd) {
4063 err = -ENOMEM;
4064 goto unlock;
4065 }
4066
4067 hci_req_init(&req, hdev);
4068
Johan Hedberg406d7802013-03-15 17:07:09 -05004069 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004070
4071 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004072 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004073 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004074 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004075 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004076 }
4077
Johan Hedberg33e38b32013-03-15 17:07:05 -05004078unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004079 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004080
Antti Julkuf6422ec2011-06-22 13:11:56 +03004081 return err;
4082}
4083
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004084static void set_bredr_scan(struct hci_request *req)
4085{
4086 struct hci_dev *hdev = req->hdev;
4087 u8 scan = 0;
4088
4089 /* Ensure that fast connectable is disabled. This function will
4090 * not do anything if the page scan parameters are already what
4091 * they should be.
4092 */
4093 write_fast_connectable(req, false);
4094
4095 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4096 scan |= SCAN_PAGE;
4097 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4098 scan |= SCAN_INQUIRY;
4099
4100 if (scan)
4101 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4102}
4103
Johan Hedberg0663ca22013-10-02 13:43:14 +03004104static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4105{
4106 struct pending_cmd *cmd;
4107
4108 BT_DBG("status 0x%02x", status);
4109
4110 hci_dev_lock(hdev);
4111
4112 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4113 if (!cmd)
4114 goto unlock;
4115
4116 if (status) {
4117 u8 mgmt_err = mgmt_status(status);
4118
4119 /* We need to restore the flag if related HCI commands
4120 * failed.
4121 */
4122 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4123
4124 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4125 } else {
4126 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4127 new_settings(hdev, cmd->sk);
4128 }
4129
4130 mgmt_pending_remove(cmd);
4131
4132unlock:
4133 hci_dev_unlock(hdev);
4134}
4135
4136static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4137{
4138 struct mgmt_mode *cp = data;
4139 struct pending_cmd *cmd;
4140 struct hci_request req;
4141 int err;
4142
4143 BT_DBG("request for %s", hdev->name);
4144
4145 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4146 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4147 MGMT_STATUS_NOT_SUPPORTED);
4148
4149 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4150 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4151 MGMT_STATUS_REJECTED);
4152
4153 if (cp->val != 0x00 && cp->val != 0x01)
4154 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4155 MGMT_STATUS_INVALID_PARAMS);
4156
4157 hci_dev_lock(hdev);
4158
4159 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4160 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4161 goto unlock;
4162 }
4163
4164 if (!hdev_is_powered(hdev)) {
4165 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004166 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4167 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4168 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4169 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4170 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4171 }
4172
4173 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4174
4175 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4176 if (err < 0)
4177 goto unlock;
4178
4179 err = new_settings(hdev, sk);
4180 goto unlock;
4181 }
4182
4183 /* Reject disabling when powered on */
4184 if (!cp->val) {
4185 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4186 MGMT_STATUS_REJECTED);
4187 goto unlock;
4188 }
4189
4190 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4191 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4192 MGMT_STATUS_BUSY);
4193 goto unlock;
4194 }
4195
4196 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4197 if (!cmd) {
4198 err = -ENOMEM;
4199 goto unlock;
4200 }
4201
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004202 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004203 * generates the correct flags.
4204 */
4205 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4206
4207 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004208
4209 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4210 set_bredr_scan(&req);
4211
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004212 /* Since only the advertising data flags will change, there
4213 * is no need to update the scan response data.
4214 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004215 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004216
Johan Hedberg0663ca22013-10-02 13:43:14 +03004217 err = hci_req_run(&req, set_bredr_complete);
4218 if (err < 0)
4219 mgmt_pending_remove(cmd);
4220
4221unlock:
4222 hci_dev_unlock(hdev);
4223 return err;
4224}
4225
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004226static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4227 void *data, u16 len)
4228{
4229 struct mgmt_mode *cp = data;
4230 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004231 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004232 int err;
4233
4234 BT_DBG("request for %s", hdev->name);
4235
4236 status = mgmt_bredr_support(hdev);
4237 if (status)
4238 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4239 status);
4240
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004241 if (!lmp_sc_capable(hdev) &&
4242 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004243 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4244 MGMT_STATUS_NOT_SUPPORTED);
4245
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004246 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004247 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4248 MGMT_STATUS_INVALID_PARAMS);
4249
4250 hci_dev_lock(hdev);
4251
4252 if (!hdev_is_powered(hdev)) {
4253 bool changed;
4254
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004255 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004256 changed = !test_and_set_bit(HCI_SC_ENABLED,
4257 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004258 if (cp->val == 0x02)
4259 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4260 else
4261 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4262 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004263 changed = test_and_clear_bit(HCI_SC_ENABLED,
4264 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004265 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4266 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004267
4268 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4269 if (err < 0)
4270 goto failed;
4271
4272 if (changed)
4273 err = new_settings(hdev, sk);
4274
4275 goto failed;
4276 }
4277
4278 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4279 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4280 MGMT_STATUS_BUSY);
4281 goto failed;
4282 }
4283
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004284 val = !!cp->val;
4285
4286 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4287 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004288 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4289 goto failed;
4290 }
4291
4292 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4293 if (!cmd) {
4294 err = -ENOMEM;
4295 goto failed;
4296 }
4297
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004298 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004299 if (err < 0) {
4300 mgmt_pending_remove(cmd);
4301 goto failed;
4302 }
4303
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004304 if (cp->val == 0x02)
4305 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4306 else
4307 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4308
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004309failed:
4310 hci_dev_unlock(hdev);
4311 return err;
4312}
4313
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004314static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4315 void *data, u16 len)
4316{
4317 struct mgmt_mode *cp = data;
4318 bool changed;
4319 int err;
4320
4321 BT_DBG("request for %s", hdev->name);
4322
4323 if (cp->val != 0x00 && cp->val != 0x01)
4324 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4325 MGMT_STATUS_INVALID_PARAMS);
4326
4327 hci_dev_lock(hdev);
4328
4329 if (cp->val)
4330 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4331 else
4332 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4333
4334 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4335 if (err < 0)
4336 goto unlock;
4337
4338 if (changed)
4339 err = new_settings(hdev, sk);
4340
4341unlock:
4342 hci_dev_unlock(hdev);
4343 return err;
4344}
4345
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004346static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4347 u16 len)
4348{
4349 struct mgmt_cp_set_privacy *cp = cp_data;
4350 bool changed;
4351 int err;
4352
4353 BT_DBG("request for %s", hdev->name);
4354
4355 if (!lmp_le_capable(hdev))
4356 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4357 MGMT_STATUS_NOT_SUPPORTED);
4358
4359 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4360 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4361 MGMT_STATUS_INVALID_PARAMS);
4362
4363 if (hdev_is_powered(hdev))
4364 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4365 MGMT_STATUS_REJECTED);
4366
4367 hci_dev_lock(hdev);
4368
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004369 /* If user space supports this command it is also expected to
4370 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4371 */
4372 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4373
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004374 if (cp->privacy) {
4375 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4376 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4377 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4378 } else {
4379 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4380 memset(hdev->irk, 0, sizeof(hdev->irk));
4381 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4382 }
4383
4384 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4385 if (err < 0)
4386 goto unlock;
4387
4388 if (changed)
4389 err = new_settings(hdev, sk);
4390
4391unlock:
4392 hci_dev_unlock(hdev);
4393 return err;
4394}
4395
Johan Hedberg41edf162014-02-18 10:19:35 +02004396static bool irk_is_valid(struct mgmt_irk_info *irk)
4397{
4398 switch (irk->addr.type) {
4399 case BDADDR_LE_PUBLIC:
4400 return true;
4401
4402 case BDADDR_LE_RANDOM:
4403 /* Two most significant bits shall be set */
4404 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4405 return false;
4406 return true;
4407 }
4408
4409 return false;
4410}
4411
4412static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4413 u16 len)
4414{
4415 struct mgmt_cp_load_irks *cp = cp_data;
4416 u16 irk_count, expected_len;
4417 int i, err;
4418
4419 BT_DBG("request for %s", hdev->name);
4420
4421 if (!lmp_le_capable(hdev))
4422 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4423 MGMT_STATUS_NOT_SUPPORTED);
4424
4425 irk_count = __le16_to_cpu(cp->irk_count);
4426
4427 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4428 if (expected_len != len) {
4429 BT_ERR("load_irks: expected %u bytes, got %u bytes",
4430 len, expected_len);
4431 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4432 MGMT_STATUS_INVALID_PARAMS);
4433 }
4434
4435 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4436
4437 for (i = 0; i < irk_count; i++) {
4438 struct mgmt_irk_info *key = &cp->irks[i];
4439
4440 if (!irk_is_valid(key))
4441 return cmd_status(sk, hdev->id,
4442 MGMT_OP_LOAD_IRKS,
4443 MGMT_STATUS_INVALID_PARAMS);
4444 }
4445
4446 hci_dev_lock(hdev);
4447
4448 hci_smp_irks_clear(hdev);
4449
4450 for (i = 0; i < irk_count; i++) {
4451 struct mgmt_irk_info *irk = &cp->irks[i];
4452 u8 addr_type;
4453
4454 if (irk->addr.type == BDADDR_LE_PUBLIC)
4455 addr_type = ADDR_LE_DEV_PUBLIC;
4456 else
4457 addr_type = ADDR_LE_DEV_RANDOM;
4458
4459 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4460 BDADDR_ANY);
4461 }
4462
4463 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4464
4465 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4466
4467 hci_dev_unlock(hdev);
4468
4469 return err;
4470}
4471
Johan Hedberg3f706b72013-01-20 14:27:16 +02004472static bool ltk_is_valid(struct mgmt_ltk_info *key)
4473{
4474 if (key->master != 0x00 && key->master != 0x01)
4475 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004476
4477 switch (key->addr.type) {
4478 case BDADDR_LE_PUBLIC:
4479 return true;
4480
4481 case BDADDR_LE_RANDOM:
4482 /* Two most significant bits shall be set */
4483 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4484 return false;
4485 return true;
4486 }
4487
4488 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004489}
4490
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004491static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004492 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004493{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004494 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4495 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004496 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004497
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004498 BT_DBG("request for %s", hdev->name);
4499
4500 if (!lmp_le_capable(hdev))
4501 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4502 MGMT_STATUS_NOT_SUPPORTED);
4503
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004504 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004505
4506 expected_len = sizeof(*cp) + key_count *
4507 sizeof(struct mgmt_ltk_info);
4508 if (expected_len != len) {
4509 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004510 len, expected_len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004511 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004512 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004513 }
4514
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004515 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004516
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004517 for (i = 0; i < key_count; i++) {
4518 struct mgmt_ltk_info *key = &cp->keys[i];
4519
Johan Hedberg3f706b72013-01-20 14:27:16 +02004520 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004521 return cmd_status(sk, hdev->id,
4522 MGMT_OP_LOAD_LONG_TERM_KEYS,
4523 MGMT_STATUS_INVALID_PARAMS);
4524 }
4525
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004526 hci_dev_lock(hdev);
4527
4528 hci_smp_ltks_clear(hdev);
4529
4530 for (i = 0; i < key_count; i++) {
4531 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004532 u8 type, addr_type;
4533
4534 if (key->addr.type == BDADDR_LE_PUBLIC)
4535 addr_type = ADDR_LE_DEV_PUBLIC;
4536 else
4537 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004538
4539 if (key->master)
4540 type = HCI_SMP_LTK;
4541 else
4542 type = HCI_SMP_LTK_SLAVE;
4543
Johan Hedberg35d70272014-02-19 14:57:47 +02004544 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4545 key->type, key->val, key->enc_size, key->ediv,
4546 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004547 }
4548
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004549 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4550 NULL, 0);
4551
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004552 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004553
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004554 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004555}
4556
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004557static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004558 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4559 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004560 bool var_len;
4561 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004562} mgmt_handlers[] = {
4563 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004564 { read_version, false, MGMT_READ_VERSION_SIZE },
4565 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4566 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4567 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4568 { set_powered, false, MGMT_SETTING_SIZE },
4569 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4570 { set_connectable, false, MGMT_SETTING_SIZE },
4571 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4572 { set_pairable, false, MGMT_SETTING_SIZE },
4573 { set_link_security, false, MGMT_SETTING_SIZE },
4574 { set_ssp, false, MGMT_SETTING_SIZE },
4575 { set_hs, false, MGMT_SETTING_SIZE },
4576 { set_le, false, MGMT_SETTING_SIZE },
4577 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4578 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4579 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4580 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4581 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4582 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4583 { disconnect, false, MGMT_DISCONNECT_SIZE },
4584 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4585 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4586 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4587 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4588 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4589 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4590 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4591 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4592 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4593 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4594 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4595 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004596 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004597 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4598 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4599 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4600 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4601 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4602 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004603 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004604 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004605 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004606 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004607 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004608 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004609 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004610 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004611 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004612};
4613
4614
Johan Hedberg03811012010-12-08 00:21:06 +02004615int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4616{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004617 void *buf;
4618 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004619 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004620 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004621 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004622 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004623 int err;
4624
4625 BT_DBG("got %zu bytes", msglen);
4626
4627 if (msglen < sizeof(*hdr))
4628 return -EINVAL;
4629
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004630 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004631 if (!buf)
4632 return -ENOMEM;
4633
4634 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4635 err = -EFAULT;
4636 goto done;
4637 }
4638
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004639 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004640 opcode = __le16_to_cpu(hdr->opcode);
4641 index = __le16_to_cpu(hdr->index);
4642 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004643
4644 if (len != msglen - sizeof(*hdr)) {
4645 err = -EINVAL;
4646 goto done;
4647 }
4648
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004649 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004650 hdev = hci_dev_get(index);
4651 if (!hdev) {
4652 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004653 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004654 goto done;
4655 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004656
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004657 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4658 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004659 err = cmd_status(sk, index, opcode,
4660 MGMT_STATUS_INVALID_INDEX);
4661 goto done;
4662 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004663 }
4664
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004665 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004666 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004667 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004668 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004669 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004670 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004671 }
4672
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004673 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004674 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004675 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004676 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004677 goto done;
4678 }
4679
Johan Hedbergbe22b542012-03-01 22:24:41 +02004680 handler = &mgmt_handlers[opcode];
4681
4682 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004683 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004684 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004685 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004686 goto done;
4687 }
4688
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004689 if (hdev)
4690 mgmt_init_hdev(sk, hdev);
4691
4692 cp = buf + sizeof(*hdr);
4693
Johan Hedbergbe22b542012-03-01 22:24:41 +02004694 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004695 if (err < 0)
4696 goto done;
4697
Johan Hedberg03811012010-12-08 00:21:06 +02004698 err = msglen;
4699
4700done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004701 if (hdev)
4702 hci_dev_put(hdev);
4703
Johan Hedberg03811012010-12-08 00:21:06 +02004704 kfree(buf);
4705 return err;
4706}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004707
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004708void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004709{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004710 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004711 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004712
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004713 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004714}
4715
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004716void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004717{
Johan Hedberg5f159032012-03-02 03:13:19 +02004718 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004719
Marcel Holtmann1514b892013-10-06 08:25:01 -07004720 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004721 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004722
Johan Hedberg744cf192011-11-08 20:40:14 +02004723 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004724
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004725 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004726}
4727
Andre Guedes6046dc32014-02-26 20:21:51 -03004728/* This function requires the caller holds hdev->lock */
4729static void restart_le_auto_conns(struct hci_dev *hdev)
4730{
4731 struct hci_conn_params *p;
4732
4733 list_for_each_entry(p, &hdev->le_conn_params, list) {
4734 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4735 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4736 }
4737}
4738
Johan Hedberg229ab392013-03-15 17:06:53 -05004739static void powered_complete(struct hci_dev *hdev, u8 status)
4740{
4741 struct cmd_lookup match = { NULL, hdev };
4742
4743 BT_DBG("status 0x%02x", status);
4744
4745 hci_dev_lock(hdev);
4746
Andre Guedes6046dc32014-02-26 20:21:51 -03004747 restart_le_auto_conns(hdev);
4748
Johan Hedberg229ab392013-03-15 17:06:53 -05004749 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4750
4751 new_settings(hdev, match.sk);
4752
4753 hci_dev_unlock(hdev);
4754
4755 if (match.sk)
4756 sock_put(match.sk);
4757}
4758
Johan Hedberg70da6242013-03-15 17:06:51 -05004759static int powered_update_hci(struct hci_dev *hdev)
4760{
Johan Hedberg890ea892013-03-15 17:06:52 -05004761 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004762 u8 link_sec;
4763
Johan Hedberg890ea892013-03-15 17:06:52 -05004764 hci_req_init(&req, hdev);
4765
Johan Hedberg70da6242013-03-15 17:06:51 -05004766 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4767 !lmp_host_ssp_capable(hdev)) {
4768 u8 ssp = 1;
4769
Johan Hedberg890ea892013-03-15 17:06:52 -05004770 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004771 }
4772
Johan Hedbergc73eee92013-04-19 18:35:21 +03004773 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4774 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004775 struct hci_cp_write_le_host_supported cp;
4776
4777 cp.le = 1;
4778 cp.simul = lmp_le_br_capable(hdev);
4779
4780 /* Check first if we already have the right
4781 * host state (host features set)
4782 */
4783 if (cp.le != lmp_host_le_capable(hdev) ||
4784 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004785 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4786 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004787 }
4788
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004789 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004790 /* Make sure the controller has a good default for
4791 * advertising data. This also applies to the case
4792 * where BR/EDR was toggled during the AUTO_OFF phase.
4793 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004794 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004795 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004796 update_scan_rsp_data(&req);
4797 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004798
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004799 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
4800 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03004801 }
4802
Johan Hedberg70da6242013-03-15 17:06:51 -05004803 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4804 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05004805 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
4806 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05004807
4808 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03004809 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
4810 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004811 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05004812 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05004813 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05004814 }
4815
Johan Hedberg229ab392013-03-15 17:06:53 -05004816 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05004817}
4818
Johan Hedberg744cf192011-11-08 20:40:14 +02004819int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02004820{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02004821 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05004822 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
4823 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004824 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004825
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004826 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
4827 return 0;
4828
Johan Hedberg5e5282b2012-02-21 16:01:30 +02004829 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05004830 if (powered_update_hci(hdev) == 0)
4831 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02004832
Johan Hedberg229ab392013-03-15 17:06:53 -05004833 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
4834 &match);
4835 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004836 }
4837
Johan Hedberg229ab392013-03-15 17:06:53 -05004838 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4839 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
4840
4841 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
4842 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
4843 zero_cod, sizeof(zero_cod), NULL);
4844
4845new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004846 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004847
4848 if (match.sk)
4849 sock_put(match.sk);
4850
Johan Hedberg7bb895d2012-02-17 01:20:00 +02004851 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02004852}
Johan Hedberg73f22f62010-12-29 16:00:25 +02004853
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004854void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03004855{
4856 struct pending_cmd *cmd;
4857 u8 status;
4858
4859 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
4860 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004861 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03004862
4863 if (err == -ERFKILL)
4864 status = MGMT_STATUS_RFKILLED;
4865 else
4866 status = MGMT_STATUS_FAILED;
4867
Marcel Holtmann3eec7052013-10-06 23:55:46 -07004868 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004869
4870 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03004871}
4872
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004873void mgmt_discoverable_timeout(struct hci_dev *hdev)
4874{
4875 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004876
4877 hci_dev_lock(hdev);
4878
4879 /* When discoverable timeout triggers, then just make sure
4880 * the limited discoverable flag is cleared. Even in the case
4881 * of a timeout triggered from general discoverable, it is
4882 * safe to unconditionally clear the flag.
4883 */
4884 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004885 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004886
4887 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03004888 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4889 u8 scan = SCAN_PAGE;
4890 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
4891 sizeof(scan), &scan);
4892 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004893 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004894 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004895 hci_req_run(&req, NULL);
4896
4897 hdev->discov_timeout = 0;
4898
Johan Hedberg9a43e252013-10-20 19:00:07 +03004899 new_settings(hdev, NULL);
4900
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07004901 hci_dev_unlock(hdev);
4902}
4903
Marcel Holtmann86a75642013-10-15 06:33:54 -07004904void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02004905{
Marcel Holtmann86a75642013-10-15 06:33:54 -07004906 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02004907
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004908 /* Nothing needed here if there's a pending command since that
4909 * commands request completion callback takes care of everything
4910 * necessary.
4911 */
4912 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07004913 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03004914
Johan Hedbergbd107992014-02-24 14:52:19 +02004915 /* Powering off may clear the scan mode - don't let that interfere */
4916 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4917 return;
4918
Johan Hedberg9a43e252013-10-20 19:00:07 +03004919 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07004920 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004921 } else {
4922 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07004923 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004924 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004925
Johan Hedberg9a43e252013-10-20 19:00:07 +03004926 if (changed) {
4927 struct hci_request req;
4928
4929 /* In case this change in discoverable was triggered by
4930 * a disabling of connectable there could be a need to
4931 * update the advertising flags.
4932 */
4933 hci_req_init(&req, hdev);
4934 update_adv_data(&req);
4935 hci_req_run(&req, NULL);
4936
Marcel Holtmann86a75642013-10-15 06:33:54 -07004937 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03004938 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02004939}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004940
Marcel Holtmanna3309162013-10-15 06:33:55 -07004941void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004942{
Marcel Holtmanna3309162013-10-15 06:33:55 -07004943 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004944
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004945 /* Nothing needed here if there's a pending command since that
4946 * commands request completion callback takes care of everything
4947 * necessary.
4948 */
4949 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07004950 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03004951
Johan Hedbergce3f24c2014-02-24 14:52:20 +02004952 /* Powering off may clear the scan mode - don't let that interfere */
4953 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4954 return;
4955
Marcel Holtmanna3309162013-10-15 06:33:55 -07004956 if (connectable)
4957 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
4958 else
4959 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004960
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02004961 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07004962 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02004963}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004964
Johan Hedberg778b2352014-02-24 14:52:17 +02004965void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
4966{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02004967 /* Powering off may stop advertising - don't let that interfere */
4968 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
4969 return;
4970
Johan Hedberg778b2352014-02-24 14:52:17 +02004971 if (advertising)
4972 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4973 else
4974 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4975}
4976
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07004977void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004978{
Johan Hedbergca69b792011-11-11 18:10:00 +02004979 u8 mgmt_err = mgmt_status(status);
4980
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004981 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02004982 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004983 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004984
4985 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02004986 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004987 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02004988}
4989
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07004990void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
4991 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004992{
Johan Hedberg86742e12011-11-07 23:13:38 +02004993 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004994
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004995 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02004996
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03004997 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02004998 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03004999 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005000 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005001 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005002 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005003
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005004 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005005}
Johan Hedbergf7520542011-01-20 12:34:39 +02005006
Johan Hedbergba74b662014-02-19 14:57:45 +02005007void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005008{
5009 struct mgmt_ev_new_long_term_key ev;
5010
5011 memset(&ev, 0, sizeof(ev));
5012
Marcel Holtmann5192d302014-02-19 17:11:58 -08005013 /* Devices using resolvable or non-resolvable random addresses
5014 * without providing an indentity resolving key don't require
5015 * to store long term keys. Their addresses will change the
5016 * next time around.
5017 *
5018 * Only when a remote device provides an identity address
5019 * make sure the long term key is stored. If the remote
5020 * identity is known, the long term keys are internally
5021 * mapped to the identity address. So allow static random
5022 * and public addresses here.
5023 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005024 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5025 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5026 ev.store_hint = 0x00;
5027 else
5028 ev.store_hint = 0x01;
5029
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005030 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005031 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08005032 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005033 ev.key.enc_size = key->enc_size;
5034 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005035 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005036
5037 if (key->type == HCI_SMP_LTK)
5038 ev.key.master = 1;
5039
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005040 memcpy(ev.key.val, key->val, sizeof(key->val));
5041
Marcel Holtmann083368f2013-10-15 14:26:29 -07005042 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005043}
5044
Johan Hedberg95fbac82014-02-19 15:18:31 +02005045void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5046{
5047 struct mgmt_ev_new_irk ev;
5048
5049 memset(&ev, 0, sizeof(ev));
5050
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005051 /* For identity resolving keys from devices that are already
5052 * using a public address or static random address, do not
5053 * ask for storing this key. The identity resolving key really
5054 * is only mandatory for devices using resovlable random
5055 * addresses.
5056 *
5057 * Storing all identity resolving keys has the downside that
5058 * they will be also loaded on next boot of they system. More
5059 * identity resolving keys, means more time during scanning is
5060 * needed to actually resolve these addresses.
5061 */
5062 if (bacmp(&irk->rpa, BDADDR_ANY))
5063 ev.store_hint = 0x01;
5064 else
5065 ev.store_hint = 0x00;
5066
Johan Hedberg95fbac82014-02-19 15:18:31 +02005067 bacpy(&ev.rpa, &irk->rpa);
5068 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5069 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5070 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5071
5072 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5073}
5074
Marcel Holtmann94933992013-10-15 10:26:39 -07005075static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5076 u8 data_len)
5077{
5078 eir[eir_len++] = sizeof(type) + data_len;
5079 eir[eir_len++] = type;
5080 memcpy(&eir[eir_len], data, data_len);
5081 eir_len += data_len;
5082
5083 return eir_len;
5084}
5085
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005086void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5087 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5088 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005089{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005090 char buf[512];
5091 struct mgmt_ev_device_connected *ev = (void *) buf;
5092 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005093
Johan Hedbergb644ba32012-01-17 21:48:47 +02005094 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005095 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005096
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005097 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005098
Johan Hedbergb644ba32012-01-17 21:48:47 +02005099 if (name_len > 0)
5100 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005101 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005102
5103 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005104 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005105 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005106
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005107 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005108
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005109 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5110 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005111}
5112
Johan Hedberg8962ee72011-01-20 12:40:27 +02005113static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5114{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005115 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005116 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005117 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005118
Johan Hedberg88c3df12012-02-09 14:27:38 +02005119 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5120 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005121
Johan Hedbergaee9b212012-02-18 15:07:59 +02005122 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005123 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005124
5125 *sk = cmd->sk;
5126 sock_hold(*sk);
5127
Johan Hedberga664b5b2011-02-19 12:06:02 -03005128 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005129}
5130
Johan Hedberg124f6e32012-02-09 13:50:12 +02005131static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005132{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005133 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005134 struct mgmt_cp_unpair_device *cp = cmd->param;
5135 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005136
5137 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005138 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5139 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005140
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005141 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5142
Johan Hedbergaee9b212012-02-18 15:07:59 +02005143 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005144
5145 mgmt_pending_remove(cmd);
5146}
5147
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005148void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005149 u8 link_type, u8 addr_type, u8 reason,
5150 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005151{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005152 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005153 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005154 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005155
Johan Hedberg8b064a32014-02-24 14:52:22 +02005156 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5157 if (power_off) {
5158 struct mgmt_mode *cp = power_off->param;
5159
5160 /* The connection is still in hci_conn_hash so test for 1
5161 * instead of 0 to know if this is the last one.
5162 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005163 if (!cp->val && hci_conn_count(hdev) == 1) {
5164 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005165 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005166 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005167 }
5168
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005169 if (!mgmt_connected)
5170 return;
5171
Andre Guedes57eb7762013-10-30 19:01:41 -03005172 if (link_type != ACL_LINK && link_type != LE_LINK)
5173 return;
5174
Johan Hedberg744cf192011-11-08 20:40:14 +02005175 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005176
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005177 bacpy(&ev.addr.bdaddr, bdaddr);
5178 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5179 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005180
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005181 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005182
5183 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005184 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005185
Johan Hedberg124f6e32012-02-09 13:50:12 +02005186 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005187 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005188}
5189
Marcel Holtmann78929242013-10-06 23:55:47 -07005190void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5191 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005192{
Andre Guedes3655bba2013-10-30 19:01:40 -03005193 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5194 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005195 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005196 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005197
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005198 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5199 hdev);
5200
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005201 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005202 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005203 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005204
Andre Guedes3655bba2013-10-30 19:01:40 -03005205 cp = cmd->param;
5206
5207 if (bacmp(bdaddr, &cp->addr.bdaddr))
5208 return;
5209
5210 if (cp->addr.type != bdaddr_type)
5211 return;
5212
Johan Hedberg88c3df12012-02-09 14:27:38 +02005213 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005214 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005215
Marcel Holtmann78929242013-10-06 23:55:47 -07005216 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5217 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005218
Johan Hedberga664b5b2011-02-19 12:06:02 -03005219 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005220}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005221
Marcel Holtmann445608d2013-10-06 23:55:48 -07005222void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5223 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005224{
5225 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005226 struct pending_cmd *power_off;
5227
5228 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5229 if (power_off) {
5230 struct mgmt_mode *cp = power_off->param;
5231
5232 /* The connection is still in hci_conn_hash so test for 1
5233 * instead of 0 to know if this is the last one.
5234 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005235 if (!cp->val && hci_conn_count(hdev) == 1) {
5236 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005237 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005238 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005239 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005240
Johan Hedberg4c659c32011-11-07 23:13:39 +02005241 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005242 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005243 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005244
Marcel Holtmann445608d2013-10-06 23:55:48 -07005245 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005246}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005247
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005248void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005249{
5250 struct mgmt_ev_pin_code_request ev;
5251
Johan Hedbergd8457692012-02-17 14:24:57 +02005252 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005253 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005254 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005255
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005256 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005257}
5258
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005259void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5260 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005261{
5262 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005263 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005264
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005265 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005266 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005267 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005268
Johan Hedbergd8457692012-02-17 14:24:57 +02005269 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005270 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005271
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005272 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5273 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005274
Johan Hedberga664b5b2011-02-19 12:06:02 -03005275 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005276}
5277
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005278void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5279 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005280{
5281 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005282 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005283
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005284 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005285 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005286 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005287
Johan Hedbergd8457692012-02-17 14:24:57 +02005288 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005289 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005290
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005291 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5292 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005293
Johan Hedberga664b5b2011-02-19 12:06:02 -03005294 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005295}
Johan Hedberga5c29682011-02-19 12:05:57 -03005296
Johan Hedberg744cf192011-11-08 20:40:14 +02005297int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005298 u8 link_type, u8 addr_type, __le32 value,
5299 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005300{
5301 struct mgmt_ev_user_confirm_request ev;
5302
Johan Hedberg744cf192011-11-08 20:40:14 +02005303 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005304
Johan Hedberg272d90d2012-02-09 15:26:12 +02005305 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005306 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005307 ev.confirm_hint = confirm_hint;
Andrei Emeltchenko78e80982012-03-09 13:00:50 +02005308 ev.value = value;
Johan Hedberga5c29682011-02-19 12:05:57 -03005309
Johan Hedberg744cf192011-11-08 20:40:14 +02005310 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005311 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005312}
5313
Johan Hedberg272d90d2012-02-09 15:26:12 +02005314int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005315 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005316{
5317 struct mgmt_ev_user_passkey_request ev;
5318
5319 BT_DBG("%s", hdev->name);
5320
Johan Hedberg272d90d2012-02-09 15:26:12 +02005321 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005322 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005323
5324 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005325 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005326}
5327
Brian Gix0df4c182011-11-16 13:53:13 -08005328static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005329 u8 link_type, u8 addr_type, u8 status,
5330 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005331{
5332 struct pending_cmd *cmd;
5333 struct mgmt_rp_user_confirm_reply rp;
5334 int err;
5335
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005336 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005337 if (!cmd)
5338 return -ENOENT;
5339
Johan Hedberg272d90d2012-02-09 15:26:12 +02005340 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005341 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005342 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005343 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005344
Johan Hedberga664b5b2011-02-19 12:06:02 -03005345 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005346
5347 return err;
5348}
5349
Johan Hedberg744cf192011-11-08 20:40:14 +02005350int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005351 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005352{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005353 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005354 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005355}
5356
Johan Hedberg272d90d2012-02-09 15:26:12 +02005357int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005358 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005359{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005360 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005361 status,
5362 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005363}
Johan Hedberg2a611692011-02-19 12:06:00 -03005364
Brian Gix604086b2011-11-23 08:28:33 -08005365int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005366 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005367{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005368 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005369 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005370}
5371
Johan Hedberg272d90d2012-02-09 15:26:12 +02005372int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005373 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005374{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005375 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005376 status,
5377 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005378}
5379
Johan Hedberg92a25252012-09-06 18:39:26 +03005380int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5381 u8 link_type, u8 addr_type, u32 passkey,
5382 u8 entered)
5383{
5384 struct mgmt_ev_passkey_notify ev;
5385
5386 BT_DBG("%s", hdev->name);
5387
5388 bacpy(&ev.addr.bdaddr, bdaddr);
5389 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5390 ev.passkey = __cpu_to_le32(passkey);
5391 ev.entered = entered;
5392
5393 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5394}
5395
Marcel Holtmanne5460992013-10-15 14:26:23 -07005396void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5397 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005398{
5399 struct mgmt_ev_auth_failed ev;
5400
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005401 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005402 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005403 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005404
Marcel Holtmanne5460992013-10-15 14:26:23 -07005405 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005406}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005407
Marcel Holtmann464996a2013-10-15 14:26:24 -07005408void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005409{
5410 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005411 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005412
5413 if (status) {
5414 u8 mgmt_err = mgmt_status(status);
5415 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005416 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005417 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005418 }
5419
Marcel Holtmann464996a2013-10-15 14:26:24 -07005420 if (test_bit(HCI_AUTH, &hdev->flags))
5421 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5422 &hdev->dev_flags);
5423 else
5424 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5425 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005426
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005427 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005428 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005429
Johan Hedberg47990ea2012-02-22 11:58:37 +02005430 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005431 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005432
5433 if (match.sk)
5434 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005435}
5436
Johan Hedberg890ea892013-03-15 17:06:52 -05005437static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005438{
Johan Hedberg890ea892013-03-15 17:06:52 -05005439 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005440 struct hci_cp_write_eir cp;
5441
Johan Hedberg976eb202012-10-24 21:12:01 +03005442 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005443 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005444
Johan Hedbergc80da272012-02-22 15:38:48 +02005445 memset(hdev->eir, 0, sizeof(hdev->eir));
5446
Johan Hedbergcacaf522012-02-21 00:52:42 +02005447 memset(&cp, 0, sizeof(cp));
5448
Johan Hedberg890ea892013-03-15 17:06:52 -05005449 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005450}
5451
Marcel Holtmann3e248562013-10-15 14:26:25 -07005452void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005453{
5454 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005455 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005456 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005457
5458 if (status) {
5459 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005460
5461 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005462 &hdev->dev_flags)) {
5463 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005464 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005465 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005466
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005467 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5468 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005469 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005470 }
5471
5472 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005473 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005474 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005475 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5476 if (!changed)
5477 changed = test_and_clear_bit(HCI_HS_ENABLED,
5478 &hdev->dev_flags);
5479 else
5480 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005481 }
5482
5483 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5484
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005485 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005486 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005487
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005488 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005489 sock_put(match.sk);
5490
Johan Hedberg890ea892013-03-15 17:06:52 -05005491 hci_req_init(&req, hdev);
5492
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005493 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005494 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005495 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005496 clear_eir(&req);
5497
5498 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005499}
5500
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005501void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5502{
5503 struct cmd_lookup match = { NULL, hdev };
5504 bool changed = false;
5505
5506 if (status) {
5507 u8 mgmt_err = mgmt_status(status);
5508
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005509 if (enable) {
5510 if (test_and_clear_bit(HCI_SC_ENABLED,
5511 &hdev->dev_flags))
5512 new_settings(hdev, NULL);
5513 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5514 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005515
5516 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5517 cmd_status_rsp, &mgmt_err);
5518 return;
5519 }
5520
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005521 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005522 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005523 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005524 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005525 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5526 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005527
5528 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5529 settings_rsp, &match);
5530
5531 if (changed)
5532 new_settings(hdev, match.sk);
5533
5534 if (match.sk)
5535 sock_put(match.sk);
5536}
5537
Johan Hedberg92da6092013-03-15 17:06:55 -05005538static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005539{
5540 struct cmd_lookup *match = data;
5541
Johan Hedberg90e70452012-02-23 23:09:40 +02005542 if (match->sk == NULL) {
5543 match->sk = cmd->sk;
5544 sock_hold(match->sk);
5545 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005546}
5547
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005548void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5549 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005550{
Johan Hedberg90e70452012-02-23 23:09:40 +02005551 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005552
Johan Hedberg92da6092013-03-15 17:06:55 -05005553 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5554 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5555 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005556
5557 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005558 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5559 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005560
5561 if (match.sk)
5562 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005563}
5564
Marcel Holtmann7667da32013-10-15 14:26:27 -07005565void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005566{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005567 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005568 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005569
Johan Hedberg13928972013-03-15 17:07:00 -05005570 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005571 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005572
5573 memset(&ev, 0, sizeof(ev));
5574 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005575 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005576
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005577 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005578 if (!cmd) {
5579 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005580
Johan Hedberg13928972013-03-15 17:07:00 -05005581 /* If this is a HCI command related to powering on the
5582 * HCI dev don't send any mgmt signals.
5583 */
5584 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005585 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005586 }
5587
Marcel Holtmann7667da32013-10-15 14:26:27 -07005588 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5589 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005590}
Szymon Jancc35938b2011-03-22 13:12:21 +01005591
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005592void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5593 u8 *randomizer192, u8 *hash256,
5594 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005595{
5596 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005597
Johan Hedberg744cf192011-11-08 20:40:14 +02005598 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005599
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005600 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005601 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005602 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005603
5604 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005605 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5606 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005607 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005608 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5609 hash256 && randomizer256) {
5610 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005611
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005612 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5613 memcpy(rp.randomizer192, randomizer192,
5614 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005615
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005616 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5617 memcpy(rp.randomizer256, randomizer256,
5618 sizeof(rp.randomizer256));
5619
5620 cmd_complete(cmd->sk, hdev->id,
5621 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5622 &rp, sizeof(rp));
5623 } else {
5624 struct mgmt_rp_read_local_oob_data rp;
5625
5626 memcpy(rp.hash, hash192, sizeof(rp.hash));
5627 memcpy(rp.randomizer, randomizer192,
5628 sizeof(rp.randomizer));
5629
5630 cmd_complete(cmd->sk, hdev->id,
5631 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5632 &rp, sizeof(rp));
5633 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005634 }
5635
5636 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005637}
Johan Hedberge17acd42011-03-30 23:57:16 +03005638
Marcel Holtmann901801b2013-10-06 23:55:51 -07005639void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5640 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8
5641 ssp, u8 *eir, u16 eir_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005642{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005643 char buf[512];
5644 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005645 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005646 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005647
Andre Guedes12602d02013-04-30 15:29:40 -03005648 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005649 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005650
Johan Hedberg1dc06092012-01-15 21:01:23 +02005651 /* Leave 5 bytes for a potential CoD field */
5652 if (sizeof(*ev) + eir_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005653 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005654
Johan Hedberg1dc06092012-01-15 21:01:23 +02005655 memset(buf, 0, sizeof(buf));
5656
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005657 irk = hci_get_irk(hdev, bdaddr, addr_type);
5658 if (irk) {
5659 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5660 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5661 } else {
5662 bacpy(&ev->addr.bdaddr, bdaddr);
5663 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5664 }
5665
Johan Hedberge319d2e2012-01-15 19:51:59 +02005666 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005667 if (cfm_name)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305668 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005669 if (!ssp)
Syam Sidhardhan612dfce2012-10-29 22:37:36 +05305670 ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005671
Johan Hedberg1dc06092012-01-15 21:01:23 +02005672 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005673 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005674
Johan Hedberg1dc06092012-01-15 21:01:23 +02005675 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5676 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005677 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005678
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005679 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005680 ev_size = sizeof(*ev) + eir_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005681
Marcel Holtmann901801b2013-10-06 23:55:51 -07005682 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005683}
Johan Hedberga88a9652011-03-30 13:18:12 +03005684
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005685void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5686 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005687{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005688 struct mgmt_ev_device_found *ev;
5689 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5690 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005691
Johan Hedbergb644ba32012-01-17 21:48:47 +02005692 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005693
Johan Hedbergb644ba32012-01-17 21:48:47 +02005694 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005695
Johan Hedbergb644ba32012-01-17 21:48:47 +02005696 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005697 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005698 ev->rssi = rssi;
5699
5700 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005701 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005702
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005703 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005704
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005705 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005706}
Johan Hedberg314b2382011-04-27 10:29:57 -04005707
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005708void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005709{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005710 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005711 struct pending_cmd *cmd;
5712
Andre Guedes343fb142011-11-22 17:14:19 -03005713 BT_DBG("%s discovering %u", hdev->name, discovering);
5714
Johan Hedberg164a6e72011-11-01 17:06:44 +02005715 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005716 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005717 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005718 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005719
5720 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005721 u8 type = hdev->discovery.type;
5722
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005723 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5724 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005725 mgmt_pending_remove(cmd);
5726 }
5727
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005728 memset(&ev, 0, sizeof(ev));
5729 ev.type = hdev->discovery.type;
5730 ev.discovering = discovering;
5731
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005732 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005733}
Antti Julku5e762442011-08-25 16:48:02 +03005734
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005735int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005736{
5737 struct pending_cmd *cmd;
5738 struct mgmt_ev_device_blocked ev;
5739
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005740 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005741
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005742 bacpy(&ev.addr.bdaddr, bdaddr);
5743 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005744
Johan Hedberg744cf192011-11-08 20:40:14 +02005745 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005746 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005747}
5748
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005749int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005750{
5751 struct pending_cmd *cmd;
5752 struct mgmt_ev_device_unblocked ev;
5753
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005754 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005755
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005756 bacpy(&ev.addr.bdaddr, bdaddr);
5757 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005758
Johan Hedberg744cf192011-11-08 20:40:14 +02005759 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005760 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005761}
Marcel Holtmann5976e602013-10-06 04:08:14 -07005762
5763static void adv_enable_complete(struct hci_dev *hdev, u8 status)
5764{
5765 BT_DBG("%s status %u", hdev->name, status);
5766
5767 /* Clear the advertising mgmt setting if we failed to re-enable it */
5768 if (status) {
5769 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005770 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005771 }
5772}
5773
5774void mgmt_reenable_advertising(struct hci_dev *hdev)
5775{
5776 struct hci_request req;
5777
Marcel Holtmannb145edc2013-10-10 09:47:54 -07005778 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07005779 return;
5780
5781 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5782 return;
5783
5784 hci_req_init(&req, hdev);
5785 enable_advertising(&req);
5786
5787 /* If this fails we have no option but to let user space know
5788 * that we've disabled advertising.
5789 */
5790 if (hci_req_run(&req, adv_enable_complete) < 0) {
5791 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07005792 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07005793 }
5794}