blob: be6f03219121226b13971c0aeadc0ff5b3e5095b [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>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmannb75cf9c2014-05-09 04:18:42 -070038#define MGMT_REVISION 6
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020088};
89
90static const u16 mgmt_events[] = {
91 MGMT_EV_CONTROLLER_ERROR,
92 MGMT_EV_INDEX_ADDED,
93 MGMT_EV_INDEX_REMOVED,
94 MGMT_EV_NEW_SETTINGS,
95 MGMT_EV_CLASS_OF_DEV_CHANGED,
96 MGMT_EV_LOCAL_NAME_CHANGED,
97 MGMT_EV_NEW_LINK_KEY,
98 MGMT_EV_NEW_LONG_TERM_KEY,
99 MGMT_EV_DEVICE_CONNECTED,
100 MGMT_EV_DEVICE_DISCONNECTED,
101 MGMT_EV_CONNECT_FAILED,
102 MGMT_EV_PIN_CODE_REQUEST,
103 MGMT_EV_USER_CONFIRM_REQUEST,
104 MGMT_EV_USER_PASSKEY_REQUEST,
105 MGMT_EV_AUTH_FAILED,
106 MGMT_EV_DEVICE_FOUND,
107 MGMT_EV_DISCOVERING,
108 MGMT_EV_DEVICE_BLOCKED,
109 MGMT_EV_DEVICE_UNBLOCKED,
110 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300111 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800112 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700113 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200114};
115
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800116#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200117
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200118#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
119 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
120
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200121struct pending_cmd {
122 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200123 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200124 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100125 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200126 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300127 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200128};
129
Johan Hedbergca69b792011-11-11 18:10:00 +0200130/* HCI to MGMT error code conversion table */
131static u8 mgmt_status_table[] = {
132 MGMT_STATUS_SUCCESS,
133 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
134 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
135 MGMT_STATUS_FAILED, /* Hardware Failure */
136 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
137 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200138 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200139 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
140 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
141 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
142 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
143 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
144 MGMT_STATUS_BUSY, /* Command Disallowed */
145 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
146 MGMT_STATUS_REJECTED, /* Rejected Security */
147 MGMT_STATUS_REJECTED, /* Rejected Personal */
148 MGMT_STATUS_TIMEOUT, /* Host Timeout */
149 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
150 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
151 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
152 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
153 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
154 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
155 MGMT_STATUS_BUSY, /* Repeated Attempts */
156 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
157 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
158 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
159 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
160 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
161 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
163 MGMT_STATUS_FAILED, /* Unspecified Error */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
165 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
166 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
167 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
168 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
169 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
170 MGMT_STATUS_FAILED, /* Unit Link Key Used */
171 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
172 MGMT_STATUS_TIMEOUT, /* Instant Passed */
173 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
174 MGMT_STATUS_FAILED, /* Transaction Collision */
175 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
176 MGMT_STATUS_REJECTED, /* QoS Rejected */
177 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
178 MGMT_STATUS_REJECTED, /* Insufficient Security */
179 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
180 MGMT_STATUS_BUSY, /* Role Switch Pending */
181 MGMT_STATUS_FAILED, /* Slot Violation */
182 MGMT_STATUS_FAILED, /* Role Switch Failed */
183 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
184 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
185 MGMT_STATUS_BUSY, /* Host Busy Pairing */
186 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
187 MGMT_STATUS_BUSY, /* Controller Busy */
188 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
189 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
190 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
191 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
192 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
193};
194
195static u8 mgmt_status(u8 hci_status)
196{
197 if (hci_status < ARRAY_SIZE(mgmt_status_table))
198 return mgmt_status_table[hci_status];
199
200 return MGMT_STATUS_FAILED;
201}
202
Szymon Janc4e51eae2011-02-25 19:05:48 +0100203static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200204{
205 struct sk_buff *skb;
206 struct mgmt_hdr *hdr;
207 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300208 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200209
Szymon Janc34eb5252011-02-28 14:10:08 +0100210 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200211
Andre Guedes790eff42012-06-07 19:05:46 -0300212 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213 if (!skb)
214 return -ENOMEM;
215
216 hdr = (void *) skb_put(skb, sizeof(*hdr));
217
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700218 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100219 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220 hdr->len = cpu_to_le16(sizeof(*ev));
221
222 ev = (void *) skb_put(skb, sizeof(*ev));
223 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200224 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300226 err = sock_queue_rcv_skb(sk, skb);
227 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228 kfree_skb(skb);
229
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300230 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200231}
232
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200233static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300234 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200235{
236 struct sk_buff *skb;
237 struct mgmt_hdr *hdr;
238 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300239 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200240
241 BT_DBG("sock %p", sk);
242
Andre Guedes790eff42012-06-07 19:05:46 -0300243 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200244 if (!skb)
245 return -ENOMEM;
246
247 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200248
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700249 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100250 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200251 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200252
Johan Hedberga38528f2011-01-22 06:46:43 +0200253 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200254 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200255 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100256
257 if (rp)
258 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200259
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300260 err = sock_queue_rcv_skb(sk, skb);
261 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200262 kfree_skb(skb);
263
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100264 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200265}
266
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300267static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
268 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200269{
270 struct mgmt_rp_read_version rp;
271
272 BT_DBG("sock %p", sk);
273
274 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200279}
280
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300281static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
282 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200283{
284 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200285 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
286 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200287 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200288 size_t rp_size;
289 int i, err;
290
291 BT_DBG("sock %p", sk);
292
293 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
294
295 rp = kmalloc(rp_size, GFP_KERNEL);
296 if (!rp)
297 return -ENOMEM;
298
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700299 rp->num_commands = cpu_to_le16(num_commands);
300 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200301
302 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
303 put_unaligned_le16(mgmt_commands[i], opcode);
304
305 for (i = 0; i < num_events; i++, opcode++)
306 put_unaligned_le16(mgmt_events[i], opcode);
307
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200308 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300309 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200310 kfree(rp);
311
312 return err;
313}
314
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
316 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200319 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200320 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200321 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300322 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323
324 BT_DBG("sock %p", sk);
325
326 read_lock(&hci_dev_list_lock);
327
328 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300329 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700330 if (d->dev_type == HCI_BREDR)
331 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 }
333
Johan Hedberga38528f2011-01-22 06:46:43 +0200334 rp_len = sizeof(*rp) + (2 * count);
335 rp = kmalloc(rp_len, GFP_ATOMIC);
336 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100337 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200338 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100339 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340
Johan Hedberg476e44c2012-10-19 20:10:46 +0300341 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200342 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200343 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200344 continue;
345
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700346 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
347 continue;
348
Marcel Holtmann1514b892013-10-06 08:25:01 -0700349 if (d->dev_type == HCI_BREDR) {
350 rp->index[count++] = cpu_to_le16(d->id);
351 BT_DBG("Added hci%u", d->id);
352 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353 }
354
Johan Hedberg476e44c2012-10-19 20:10:46 +0300355 rp->num_controllers = cpu_to_le16(count);
356 rp_len = sizeof(*rp) + (2 * count);
357
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358 read_unlock(&hci_dev_list_lock);
359
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200360 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300361 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362
Johan Hedberga38528f2011-01-22 06:46:43 +0200363 kfree(rp);
364
365 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366}
367
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200368static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200369{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200370 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200371
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200373 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800374 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200375
Andre Guedesed3fa312012-07-24 15:03:46 -0300376 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300377 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500378 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
379 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300380 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_BREDR;
382 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700383
384 if (lmp_ssp_capable(hdev)) {
385 settings |= MGMT_SETTING_SSP;
386 settings |= MGMT_SETTING_HS;
387 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800388
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800389 if (lmp_sc_capable(hdev) ||
390 test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800391 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700392 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100393
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300394 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200395 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300396 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200397 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300398 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200399
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200400 return settings;
401}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200402
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200403static u32 get_current_settings(struct hci_dev *hdev)
404{
405 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200406
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200407 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100408 settings |= MGMT_SETTING_POWERED;
409
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200410 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411 settings |= MGMT_SETTING_CONNECTABLE;
412
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500413 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
414 settings |= MGMT_SETTING_FAST_CONNECTABLE;
415
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200416 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200417 settings |= MGMT_SETTING_DISCOVERABLE;
418
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200419 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_PAIRABLE;
421
Johan Hedberg56f87902013-10-02 13:43:13 +0300422 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_BREDR;
424
Johan Hedberg06199cf2012-02-22 16:37:11 +0200425 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200427
Johan Hedberg47990ea2012-02-22 11:58:37 +0200428 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200430
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200431 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200433
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200434 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
435 settings |= MGMT_SETTING_HS;
436
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200437 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300438 settings |= MGMT_SETTING_ADVERTISING;
439
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800440 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
441 settings |= MGMT_SETTING_SECURE_CONN;
442
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800443 if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
444 settings |= MGMT_SETTING_DEBUG_KEYS;
445
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200446 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
447 settings |= MGMT_SETTING_PRIVACY;
448
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200449 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200450}
451
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300452#define PNP_INFO_SVCLASS_ID 0x1200
453
Johan Hedberg213202e2013-01-27 00:31:33 +0200454static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
455{
456 u8 *ptr = data, *uuids_start = NULL;
457 struct bt_uuid *uuid;
458
459 if (len < 4)
460 return ptr;
461
462 list_for_each_entry(uuid, &hdev->uuids, list) {
463 u16 uuid16;
464
465 if (uuid->size != 16)
466 continue;
467
468 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
469 if (uuid16 < 0x1100)
470 continue;
471
472 if (uuid16 == PNP_INFO_SVCLASS_ID)
473 continue;
474
475 if (!uuids_start) {
476 uuids_start = ptr;
477 uuids_start[0] = 1;
478 uuids_start[1] = EIR_UUID16_ALL;
479 ptr += 2;
480 }
481
482 /* Stop if not enough space to put next UUID */
483 if ((ptr - data) + sizeof(u16) > len) {
484 uuids_start[1] = EIR_UUID16_SOME;
485 break;
486 }
487
488 *ptr++ = (uuid16 & 0x00ff);
489 *ptr++ = (uuid16 & 0xff00) >> 8;
490 uuids_start[0] += sizeof(uuid16);
491 }
492
493 return ptr;
494}
495
Johan Hedbergcdf19632013-01-27 00:31:34 +0200496static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
497{
498 u8 *ptr = data, *uuids_start = NULL;
499 struct bt_uuid *uuid;
500
501 if (len < 6)
502 return ptr;
503
504 list_for_each_entry(uuid, &hdev->uuids, list) {
505 if (uuid->size != 32)
506 continue;
507
508 if (!uuids_start) {
509 uuids_start = ptr;
510 uuids_start[0] = 1;
511 uuids_start[1] = EIR_UUID32_ALL;
512 ptr += 2;
513 }
514
515 /* Stop if not enough space to put next UUID */
516 if ((ptr - data) + sizeof(u32) > len) {
517 uuids_start[1] = EIR_UUID32_SOME;
518 break;
519 }
520
521 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
522 ptr += sizeof(u32);
523 uuids_start[0] += sizeof(u32);
524 }
525
526 return ptr;
527}
528
Johan Hedbergc00d5752013-01-27 00:31:35 +0200529static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
530{
531 u8 *ptr = data, *uuids_start = NULL;
532 struct bt_uuid *uuid;
533
534 if (len < 18)
535 return ptr;
536
537 list_for_each_entry(uuid, &hdev->uuids, list) {
538 if (uuid->size != 128)
539 continue;
540
541 if (!uuids_start) {
542 uuids_start = ptr;
543 uuids_start[0] = 1;
544 uuids_start[1] = EIR_UUID128_ALL;
545 ptr += 2;
546 }
547
548 /* Stop if not enough space to put next UUID */
549 if ((ptr - data) + 16 > len) {
550 uuids_start[1] = EIR_UUID128_SOME;
551 break;
552 }
553
554 memcpy(ptr, uuid->uuid, 16);
555 ptr += 16;
556 uuids_start[0] += 16;
557 }
558
559 return ptr;
560}
561
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300562static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
563{
564 struct pending_cmd *cmd;
565
566 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
567 if (cmd->opcode == opcode)
568 return cmd;
569 }
570
571 return NULL;
572}
573
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700574static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
575{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700576 u8 ad_len = 0;
577 size_t name_len;
578
579 name_len = strlen(hdev->dev_name);
580 if (name_len > 0) {
581 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
582
583 if (name_len > max_len) {
584 name_len = max_len;
585 ptr[1] = EIR_NAME_SHORT;
586 } else
587 ptr[1] = EIR_NAME_COMPLETE;
588
589 ptr[0] = name_len + 1;
590
591 memcpy(ptr + 2, hdev->dev_name, name_len);
592
593 ad_len += (name_len + 2);
594 ptr += (name_len + 2);
595 }
596
597 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700598}
599
600static void update_scan_rsp_data(struct hci_request *req)
601{
602 struct hci_dev *hdev = req->hdev;
603 struct hci_cp_le_set_scan_rsp_data cp;
604 u8 len;
605
Johan Hedberg7751ef12013-10-19 23:38:15 +0300606 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700607 return;
608
609 memset(&cp, 0, sizeof(cp));
610
611 len = create_scan_rsp_data(hdev, cp.data);
612
Johan Hedbergeb438b52013-10-16 15:31:07 +0300613 if (hdev->scan_rsp_data_len == len &&
614 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615 return;
616
Johan Hedbergeb438b52013-10-16 15:31:07 +0300617 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
618 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700619
620 cp.length = len;
621
622 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
623}
624
Johan Hedberg9a43e252013-10-20 19:00:07 +0300625static u8 get_adv_discov_flags(struct hci_dev *hdev)
626{
627 struct pending_cmd *cmd;
628
629 /* If there's a pending mgmt command the flags will not yet have
630 * their final values, so check for this first.
631 */
632 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
633 if (cmd) {
634 struct mgmt_mode *cp = cmd->param;
635 if (cp->val == 0x01)
636 return LE_AD_GENERAL;
637 else if (cp->val == 0x02)
638 return LE_AD_LIMITED;
639 } else {
640 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
641 return LE_AD_LIMITED;
642 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
643 return LE_AD_GENERAL;
644 }
645
646 return 0;
647}
648
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700649static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700650{
651 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700652
Johan Hedberg9a43e252013-10-20 19:00:07 +0300653 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700654
Johan Hedberge8340042014-01-30 11:16:50 -0800655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700656 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700657
658 if (flags) {
659 BT_DBG("adv flags 0x%02x", flags);
660
661 ptr[0] = 2;
662 ptr[1] = EIR_FLAGS;
663 ptr[2] = flags;
664
665 ad_len += 3;
666 ptr += 3;
667 }
668
669 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
670 ptr[0] = 2;
671 ptr[1] = EIR_TX_POWER;
672 ptr[2] = (u8) hdev->adv_tx_power;
673
674 ad_len += 3;
675 ptr += 3;
676 }
677
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678 return ad_len;
679}
680
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700681static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682{
683 struct hci_dev *hdev = req->hdev;
684 struct hci_cp_le_set_adv_data cp;
685 u8 len;
686
Johan Hedberg10994ce2013-10-19 23:38:16 +0300687 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700688 return;
689
690 memset(&cp, 0, sizeof(cp));
691
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700692 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700693
694 if (hdev->adv_data_len == len &&
695 memcmp(cp.data, hdev->adv_data, len) == 0)
696 return;
697
698 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
699 hdev->adv_data_len = len;
700
701 cp.length = len;
702
703 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
704}
705
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300706static void create_eir(struct hci_dev *hdev, u8 *data)
707{
708 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300709 size_t name_len;
710
711 name_len = strlen(hdev->dev_name);
712
713 if (name_len > 0) {
714 /* EIR Data type */
715 if (name_len > 48) {
716 name_len = 48;
717 ptr[1] = EIR_NAME_SHORT;
718 } else
719 ptr[1] = EIR_NAME_COMPLETE;
720
721 /* EIR Data length */
722 ptr[0] = name_len + 1;
723
724 memcpy(ptr + 2, hdev->dev_name, name_len);
725
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726 ptr += (name_len + 2);
727 }
728
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100729 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700730 ptr[0] = 2;
731 ptr[1] = EIR_TX_POWER;
732 ptr[2] = (u8) hdev->inq_tx_power;
733
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700734 ptr += 3;
735 }
736
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700737 if (hdev->devid_source > 0) {
738 ptr[0] = 9;
739 ptr[1] = EIR_DEVICE_ID;
740
741 put_unaligned_le16(hdev->devid_source, ptr + 2);
742 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
743 put_unaligned_le16(hdev->devid_product, ptr + 6);
744 put_unaligned_le16(hdev->devid_version, ptr + 8);
745
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700746 ptr += 10;
747 }
748
Johan Hedberg213202e2013-01-27 00:31:33 +0200749 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200750 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200751 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752}
753
Johan Hedberg890ea892013-03-15 17:06:52 -0500754static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300755{
Johan Hedberg890ea892013-03-15 17:06:52 -0500756 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300757 struct hci_cp_write_eir cp;
758
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200759 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500760 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200761
Johan Hedberg976eb202012-10-24 21:12:01 +0300762 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200765 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200768 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500769 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300770
771 memset(&cp, 0, sizeof(cp));
772
773 create_eir(hdev, cp.data);
774
775 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777
778 memcpy(hdev->eir, cp.data, sizeof(cp.data));
779
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781}
782
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783static u8 get_service_classes(struct hci_dev *hdev)
784{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 u8 val = 0;
787
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300788 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200789 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200790
791 return val;
792}
793
Johan Hedberg890ea892013-03-15 17:06:52 -0500794static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200795{
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200797 u8 cod[3];
798
799 BT_DBG("%s", hdev->name);
800
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200801 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500802 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200803
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300804 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
805 return;
806
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200807 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500808 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809
810 cod[0] = hdev->minor_class;
811 cod[1] = hdev->major_class;
812 cod[2] = get_service_classes(hdev);
813
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700814 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
815 cod[1] |= 0x20;
816
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500818 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200819
Johan Hedberg890ea892013-03-15 17:06:52 -0500820 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821}
822
Johan Hedberga4858cb2014-02-25 19:56:31 +0200823static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200824{
825 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200826
827 /* If there's a pending mgmt command the flag will not yet have
828 * it's final value, so check for this first.
829 */
830 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
831 if (cmd) {
832 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834 }
835
Johan Hedberga4858cb2014-02-25 19:56:31 +0200836 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200837}
838
839static void enable_advertising(struct hci_request *req)
840{
841 struct hci_dev *hdev = req->hdev;
842 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200843 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200844 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200845
Johan Hedberg8d972502014-02-28 12:54:14 +0200846 /* Clear the HCI_ADVERTISING bit temporarily so that the
847 * hci_update_random_address knows that it's safe to go ahead
848 * and write a new random address. The flag will be set back on
849 * as soon as the SET_ADV_ENABLE HCI command completes.
850 */
851 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
852
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200854
Johan Hedberga4858cb2014-02-25 19:56:31 +0200855 /* Set require_privacy to true only when non-connectable
856 * advertising is used. In that case it is fine to use a
857 * non-resolvable private address.
858 */
859 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200860 return;
861
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800862 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700863 cp.min_interval = cpu_to_le16(0x0800);
864 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200865 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200866 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200867 cp.channel_map = hdev->le_adv_channel_map;
868
869 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
870
871 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
872}
873
874static void disable_advertising(struct hci_request *req)
875{
876 u8 enable = 0x00;
877
878 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
879}
880
Johan Hedberg7d785252011-12-15 00:47:39 +0200881static void service_cache_off(struct work_struct *work)
882{
883 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300884 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500885 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200886
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200887 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200888 return;
889
Johan Hedberg890ea892013-03-15 17:06:52 -0500890 hci_req_init(&req, hdev);
891
Johan Hedberg7d785252011-12-15 00:47:39 +0200892 hci_dev_lock(hdev);
893
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 update_eir(&req);
895 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200896
897 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500898
899 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200900}
901
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200902static void rpa_expired(struct work_struct *work)
903{
904 struct hci_dev *hdev = container_of(work, struct hci_dev,
905 rpa_expired.work);
906 struct hci_request req;
907
908 BT_DBG("");
909
910 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
911
912 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
913 hci_conn_num(hdev, LE_LINK) > 0)
914 return;
915
916 /* The generation of a new RPA and programming it into the
917 * controller happens in the enable_advertising() function.
918 */
919
920 hci_req_init(&req, hdev);
921
922 disable_advertising(&req);
923 enable_advertising(&req);
924
925 hci_req_run(&req, NULL);
926}
927
Johan Hedberg6a919082012-02-28 06:17:26 +0200928static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200929{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200930 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200931 return;
932
Johan Hedberg4f87da82012-03-02 19:55:56 +0200933 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200934 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200935
Johan Hedberg4f87da82012-03-02 19:55:56 +0200936 /* Non-mgmt controlled devices get this bit set
937 * implicitly so that pairing works for them, however
938 * for mgmt we require user-space to explicitly enable
939 * it
940 */
941 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200942}
943
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200944static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300945 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200946{
947 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200948
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200949 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200950
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300951 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200952
Johan Hedberg03811012010-12-08 00:21:06 +0200953 memset(&rp, 0, sizeof(rp));
954
Johan Hedberg03811012010-12-08 00:21:06 +0200955 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200956
957 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200958 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200959
960 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
961 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
962
963 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200964
965 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200966 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300968 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200969
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200970 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200972}
973
974static void mgmt_pending_free(struct pending_cmd *cmd)
975{
976 sock_put(cmd->sk);
977 kfree(cmd->param);
978 kfree(cmd);
979}
980
981static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300982 struct hci_dev *hdev, void *data,
983 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200984{
985 struct pending_cmd *cmd;
986
Andre Guedes12b94562012-06-07 19:05:45 -0300987 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200988 if (!cmd)
989 return NULL;
990
991 cmd->opcode = opcode;
992 cmd->index = hdev->id;
993
Andre Guedes12b94562012-06-07 19:05:45 -0300994 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200995 if (!cmd->param) {
996 kfree(cmd);
997 return NULL;
998 }
999
1000 if (data)
1001 memcpy(cmd->param, data, len);
1002
1003 cmd->sk = sk;
1004 sock_hold(sk);
1005
1006 list_add(&cmd->list, &hdev->mgmt_pending);
1007
1008 return cmd;
1009}
1010
1011static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001012 void (*cb)(struct pending_cmd *cmd,
1013 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001014 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001015{
Andre Guedesa3d09352013-02-01 11:21:30 -03001016 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001017
Andre Guedesa3d09352013-02-01 11:21:30 -03001018 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001019 if (opcode > 0 && cmd->opcode != opcode)
1020 continue;
1021
1022 cb(cmd, data);
1023 }
1024}
1025
Johan Hedberg03811012010-12-08 00:21:06 +02001026static void mgmt_pending_remove(struct pending_cmd *cmd)
1027{
1028 list_del(&cmd->list);
1029 mgmt_pending_free(cmd);
1030}
1031
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001032static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001033{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001034 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001035
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001036 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001037 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001038}
1039
Johan Hedberg8b064a32014-02-24 14:52:22 +02001040static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1041{
1042 BT_DBG("%s status 0x%02x", hdev->name, status);
1043
Johan Hedberga3172b72014-02-28 09:33:44 +02001044 if (hci_conn_count(hdev) == 0) {
1045 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001046 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001047 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001048}
1049
Johan Hedberg21a60d32014-06-10 14:05:58 +03001050static void hci_stop_discovery(struct hci_request *req)
1051{
1052 struct hci_dev *hdev = req->hdev;
1053 struct hci_cp_remote_name_req_cancel cp;
1054 struct inquiry_entry *e;
1055
1056 switch (hdev->discovery.state) {
1057 case DISCOVERY_FINDING:
1058 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1059 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1060 } else {
1061 cancel_delayed_work(&hdev->le_scan_disable);
1062 hci_req_add_le_scan_disable(req);
1063 }
1064
1065 break;
1066
1067 case DISCOVERY_RESOLVING:
1068 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1069 NAME_PENDING);
1070 if (!e)
1071 return;
1072
1073 bacpy(&cp.bdaddr, &e->data.bdaddr);
1074 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1075 &cp);
1076
1077 break;
1078
1079 default:
1080 /* Passive scanning */
1081 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1082 hci_req_add_le_scan_disable(req);
1083 break;
1084 }
1085}
1086
Johan Hedberg8b064a32014-02-24 14:52:22 +02001087static int clean_up_hci_state(struct hci_dev *hdev)
1088{
1089 struct hci_request req;
1090 struct hci_conn *conn;
1091
1092 hci_req_init(&req, hdev);
1093
1094 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1095 test_bit(HCI_PSCAN, &hdev->flags)) {
1096 u8 scan = 0x00;
1097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1098 }
1099
1100 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1101 disable_advertising(&req);
1102
1103 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001104 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001105 }
1106
1107 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1108 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001109 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001110
Johan Hedbergc9910d02014-02-27 14:35:12 +02001111 switch (conn->state) {
1112 case BT_CONNECTED:
1113 case BT_CONFIG:
1114 dc.handle = cpu_to_le16(conn->handle);
1115 dc.reason = 0x15; /* Terminated due to Power Off */
1116 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1117 break;
1118 case BT_CONNECT:
1119 if (conn->type == LE_LINK)
1120 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1121 0, NULL);
1122 else if (conn->type == ACL_LINK)
1123 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1124 6, &conn->dst);
1125 break;
1126 case BT_CONNECT2:
1127 bacpy(&rej.bdaddr, &conn->dst);
1128 rej.reason = 0x15; /* Terminated due to Power Off */
1129 if (conn->type == ACL_LINK)
1130 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1131 sizeof(rej), &rej);
1132 else if (conn->type == SCO_LINK)
1133 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1134 sizeof(rej), &rej);
1135 break;
1136 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001137 }
1138
1139 return hci_req_run(&req, clean_up_hci_complete);
1140}
1141
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001142static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001143 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001144{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001145 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001146 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001147 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001149 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001150
Johan Hedberga7e80f22013-01-09 16:05:19 +02001151 if (cp->val != 0x00 && cp->val != 0x01)
1152 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1153 MGMT_STATUS_INVALID_PARAMS);
1154
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001155 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001156
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001157 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1158 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1159 MGMT_STATUS_BUSY);
1160 goto failed;
1161 }
1162
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001163 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1164 cancel_delayed_work(&hdev->power_off);
1165
1166 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001167 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1168 data, len);
1169 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001170 goto failed;
1171 }
1172 }
1173
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001174 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001175 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001176 goto failed;
1177 }
1178
Johan Hedberg03811012010-12-08 00:21:06 +02001179 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1180 if (!cmd) {
1181 err = -ENOMEM;
1182 goto failed;
1183 }
1184
Johan Hedberg8b064a32014-02-24 14:52:22 +02001185 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001186 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001187 err = 0;
1188 } else {
1189 /* Disconnect connections, stop scans, etc */
1190 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001191 if (!err)
1192 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1193 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001194
Johan Hedberg8b064a32014-02-24 14:52:22 +02001195 /* ENODATA means there were no HCI commands queued */
1196 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001197 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001198 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1199 err = 0;
1200 }
1201 }
Johan Hedberg03811012010-12-08 00:21:06 +02001202
1203failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001204 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001205 return err;
1206}
1207
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001208static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1209 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001210{
1211 struct sk_buff *skb;
1212 struct mgmt_hdr *hdr;
1213
Andre Guedes790eff42012-06-07 19:05:46 -03001214 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001215 if (!skb)
1216 return -ENOMEM;
1217
1218 hdr = (void *) skb_put(skb, sizeof(*hdr));
1219 hdr->opcode = cpu_to_le16(event);
1220 if (hdev)
1221 hdr->index = cpu_to_le16(hdev->id);
1222 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001223 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001224 hdr->len = cpu_to_le16(data_len);
1225
1226 if (data)
1227 memcpy(skb_put(skb, data_len), data, data_len);
1228
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001229 /* Time stamp */
1230 __net_timestamp(skb);
1231
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001232 hci_send_to_control(skb, skip_sk);
1233 kfree_skb(skb);
1234
1235 return 0;
1236}
1237
1238static int new_settings(struct hci_dev *hdev, struct sock *skip)
1239{
1240 __le32 ev;
1241
1242 ev = cpu_to_le32(get_current_settings(hdev));
1243
1244 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1245}
1246
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001247struct cmd_lookup {
1248 struct sock *sk;
1249 struct hci_dev *hdev;
1250 u8 mgmt_status;
1251};
1252
1253static void settings_rsp(struct pending_cmd *cmd, void *data)
1254{
1255 struct cmd_lookup *match = data;
1256
1257 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1258
1259 list_del(&cmd->list);
1260
1261 if (match->sk == NULL) {
1262 match->sk = cmd->sk;
1263 sock_hold(match->sk);
1264 }
1265
1266 mgmt_pending_free(cmd);
1267}
1268
1269static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1270{
1271 u8 *status = data;
1272
1273 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1274 mgmt_pending_remove(cmd);
1275}
1276
Johan Hedberge6fe7982013-10-02 15:45:22 +03001277static u8 mgmt_bredr_support(struct hci_dev *hdev)
1278{
1279 if (!lmp_bredr_capable(hdev))
1280 return MGMT_STATUS_NOT_SUPPORTED;
1281 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1282 return MGMT_STATUS_REJECTED;
1283 else
1284 return MGMT_STATUS_SUCCESS;
1285}
1286
1287static u8 mgmt_le_support(struct hci_dev *hdev)
1288{
1289 if (!lmp_le_capable(hdev))
1290 return MGMT_STATUS_NOT_SUPPORTED;
1291 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1292 return MGMT_STATUS_REJECTED;
1293 else
1294 return MGMT_STATUS_SUCCESS;
1295}
1296
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001297static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1298{
1299 struct pending_cmd *cmd;
1300 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001301 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001302 bool changed;
1303
1304 BT_DBG("status 0x%02x", status);
1305
1306 hci_dev_lock(hdev);
1307
1308 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1309 if (!cmd)
1310 goto unlock;
1311
1312 if (status) {
1313 u8 mgmt_err = mgmt_status(status);
1314 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001315 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001316 goto remove_cmd;
1317 }
1318
1319 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001320 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001321 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1322 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001323
1324 if (hdev->discov_timeout > 0) {
1325 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1326 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1327 to);
1328 }
1329 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001330 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1331 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001332 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001333
1334 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1335
1336 if (changed)
1337 new_settings(hdev, cmd->sk);
1338
Marcel Holtmann970ba522013-10-15 06:33:57 -07001339 /* When the discoverable mode gets changed, make sure
1340 * that class of device has the limited discoverable
1341 * bit correctly set.
1342 */
1343 hci_req_init(&req, hdev);
1344 update_class(&req);
1345 hci_req_run(&req, NULL);
1346
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001347remove_cmd:
1348 mgmt_pending_remove(cmd);
1349
1350unlock:
1351 hci_dev_unlock(hdev);
1352}
1353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001354static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001355 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001356{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001357 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001358 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001359 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001360 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001361 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001362 int err;
1363
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001364 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001365
Johan Hedberg9a43e252013-10-20 19:00:07 +03001366 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1367 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001368 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001369 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001370
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001371 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001372 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1373 MGMT_STATUS_INVALID_PARAMS);
1374
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001375 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001376
1377 /* Disabling discoverable requires that no timeout is set,
1378 * and enabling limited discoverable requires a timeout.
1379 */
1380 if ((cp->val == 0x00 && timeout > 0) ||
1381 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001382 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001383 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001384
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001385 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001386
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001387 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001388 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001389 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001390 goto failed;
1391 }
1392
1393 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001394 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001395 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001396 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001397 goto failed;
1398 }
1399
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001400 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001401 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001402 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001403 goto failed;
1404 }
1405
1406 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001407 bool changed = false;
1408
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001409 /* Setting limited discoverable when powered off is
1410 * not a valid operation since it requires a timeout
1411 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1412 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001413 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1414 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1415 changed = true;
1416 }
1417
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001418 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001419 if (err < 0)
1420 goto failed;
1421
1422 if (changed)
1423 err = new_settings(hdev, sk);
1424
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001425 goto failed;
1426 }
1427
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001428 /* If the current mode is the same, then just update the timeout
1429 * value with the new value. And if only the timeout gets updated,
1430 * then no need for any HCI transactions.
1431 */
1432 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1433 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1434 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001435 cancel_delayed_work(&hdev->discov_off);
1436 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001437
Marcel Holtmann36261542013-10-15 08:28:51 -07001438 if (cp->val && hdev->discov_timeout > 0) {
1439 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001440 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001441 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001442 }
1443
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001444 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001445 goto failed;
1446 }
1447
1448 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1449 if (!cmd) {
1450 err = -ENOMEM;
1451 goto failed;
1452 }
1453
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001454 /* Cancel any potential discoverable timeout that might be
1455 * still active and store new timeout value. The arming of
1456 * the timeout happens in the complete handler.
1457 */
1458 cancel_delayed_work(&hdev->discov_off);
1459 hdev->discov_timeout = timeout;
1460
Johan Hedbergb456f872013-10-19 23:38:22 +03001461 /* Limited discoverable mode */
1462 if (cp->val == 0x02)
1463 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1464 else
1465 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1466
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001467 hci_req_init(&req, hdev);
1468
Johan Hedberg9a43e252013-10-20 19:00:07 +03001469 /* The procedure for LE-only controllers is much simpler - just
1470 * update the advertising data.
1471 */
1472 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1473 goto update_ad;
1474
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001475 scan = SCAN_PAGE;
1476
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001477 if (cp->val) {
1478 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001479
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001480 if (cp->val == 0x02) {
1481 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001482 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001483 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1484 hci_cp.iac_lap[1] = 0x8b;
1485 hci_cp.iac_lap[2] = 0x9e;
1486 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1487 hci_cp.iac_lap[4] = 0x8b;
1488 hci_cp.iac_lap[5] = 0x9e;
1489 } else {
1490 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001491 hci_cp.num_iac = 1;
1492 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1493 hci_cp.iac_lap[1] = 0x8b;
1494 hci_cp.iac_lap[2] = 0x9e;
1495 }
1496
1497 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1498 (hci_cp.num_iac * 3) + 1, &hci_cp);
1499
1500 scan |= SCAN_INQUIRY;
1501 } else {
1502 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1503 }
1504
1505 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001506
Johan Hedberg9a43e252013-10-20 19:00:07 +03001507update_ad:
1508 update_adv_data(&req);
1509
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001510 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001511 if (err < 0)
1512 mgmt_pending_remove(cmd);
1513
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001514failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001515 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001516 return err;
1517}
1518
Johan Hedberg406d7802013-03-15 17:07:09 -05001519static void write_fast_connectable(struct hci_request *req, bool enable)
1520{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001521 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001522 struct hci_cp_write_page_scan_activity acp;
1523 u8 type;
1524
Johan Hedberg547003b2013-10-21 16:51:53 +03001525 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1526 return;
1527
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001528 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1529 return;
1530
Johan Hedberg406d7802013-03-15 17:07:09 -05001531 if (enable) {
1532 type = PAGE_SCAN_TYPE_INTERLACED;
1533
1534 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001535 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001536 } else {
1537 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1538
1539 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001540 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001541 }
1542
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001543 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001544
Johan Hedbergbd98b992013-03-15 17:07:13 -05001545 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1546 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1547 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1548 sizeof(acp), &acp);
1549
1550 if (hdev->page_scan_type != type)
1551 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001552}
1553
Johan Hedberg2b76f452013-03-15 17:07:04 -05001554static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1555{
1556 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001557 struct mgmt_mode *cp;
1558 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001559
1560 BT_DBG("status 0x%02x", status);
1561
1562 hci_dev_lock(hdev);
1563
1564 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1565 if (!cmd)
1566 goto unlock;
1567
Johan Hedberg37438c12013-10-14 16:20:05 +03001568 if (status) {
1569 u8 mgmt_err = mgmt_status(status);
1570 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1571 goto remove_cmd;
1572 }
1573
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001574 cp = cmd->param;
1575 if (cp->val)
1576 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1577 else
1578 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1579
Johan Hedberg2b76f452013-03-15 17:07:04 -05001580 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1581
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001582 if (changed)
1583 new_settings(hdev, cmd->sk);
1584
Johan Hedberg37438c12013-10-14 16:20:05 +03001585remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001586 mgmt_pending_remove(cmd);
1587
1588unlock:
1589 hci_dev_unlock(hdev);
1590}
1591
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001592static int set_connectable_update_settings(struct hci_dev *hdev,
1593 struct sock *sk, u8 val)
1594{
1595 bool changed = false;
1596 int err;
1597
1598 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1599 changed = true;
1600
1601 if (val) {
1602 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603 } else {
1604 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1605 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1606 }
1607
1608 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1609 if (err < 0)
1610 return err;
1611
1612 if (changed)
1613 return new_settings(hdev, sk);
1614
1615 return 0;
1616}
1617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001618static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001619 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001620{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001621 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001622 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001623 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001624 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001625 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001626
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001628
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001629 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1630 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001631 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001632 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001633
Johan Hedberga7e80f22013-01-09 16:05:19 +02001634 if (cp->val != 0x00 && cp->val != 0x01)
1635 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1636 MGMT_STATUS_INVALID_PARAMS);
1637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001638 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001639
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001640 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001641 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001642 goto failed;
1643 }
1644
1645 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001646 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001647 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001648 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001649 goto failed;
1650 }
1651
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001652 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1653 if (!cmd) {
1654 err = -ENOMEM;
1655 goto failed;
1656 }
1657
Johan Hedberg2b76f452013-03-15 17:07:04 -05001658 hci_req_init(&req, hdev);
1659
Johan Hedberg9a43e252013-10-20 19:00:07 +03001660 /* If BR/EDR is not enabled and we disable advertising as a
1661 * by-product of disabling connectable, we need to update the
1662 * advertising flags.
1663 */
1664 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1665 if (!cp->val) {
1666 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1667 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1668 }
1669 update_adv_data(&req);
1670 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001671 if (cp->val) {
1672 scan = SCAN_PAGE;
1673 } else {
1674 scan = 0;
1675
1676 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001677 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001678 cancel_delayed_work(&hdev->discov_off);
1679 }
1680
1681 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1682 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001683
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001684 /* If we're going from non-connectable to connectable or
1685 * vice-versa when fast connectable is enabled ensure that fast
1686 * connectable gets disabled. write_fast_connectable won't do
1687 * anything if the page scan parameters are already what they
1688 * should be.
1689 */
1690 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001691 write_fast_connectable(&req, false);
1692
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001693 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1694 hci_conn_num(hdev, LE_LINK) == 0) {
1695 disable_advertising(&req);
1696 enable_advertising(&req);
1697 }
1698
Johan Hedberg2b76f452013-03-15 17:07:04 -05001699 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001700 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001701 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001702 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001703 err = set_connectable_update_settings(hdev, sk,
1704 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001705 goto failed;
1706 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001707
1708failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001709 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001710 return err;
1711}
1712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001713static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001714 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001715{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001716 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001717 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001718 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001720 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001721
Johan Hedberga7e80f22013-01-09 16:05:19 +02001722 if (cp->val != 0x00 && cp->val != 0x01)
1723 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1724 MGMT_STATUS_INVALID_PARAMS);
1725
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001726 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001727
1728 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001729 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001730 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001731 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001733 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001735 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001736
Marcel Holtmann55594352013-10-06 16:11:57 -07001737 if (changed)
1738 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001739
Marcel Holtmann55594352013-10-06 16:11:57 -07001740unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001742 return err;
1743}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001744
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001745static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1746 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001747{
1748 struct mgmt_mode *cp = data;
1749 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001750 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001751 int err;
1752
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001753 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001754
Johan Hedberge6fe7982013-10-02 15:45:22 +03001755 status = mgmt_bredr_support(hdev);
1756 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001757 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001758 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001759
Johan Hedberga7e80f22013-01-09 16:05:19 +02001760 if (cp->val != 0x00 && cp->val != 0x01)
1761 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1762 MGMT_STATUS_INVALID_PARAMS);
1763
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001764 hci_dev_lock(hdev);
1765
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001766 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001767 bool changed = false;
1768
1769 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001770 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001771 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1772 changed = true;
1773 }
1774
1775 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1776 if (err < 0)
1777 goto failed;
1778
1779 if (changed)
1780 err = new_settings(hdev, sk);
1781
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001782 goto failed;
1783 }
1784
1785 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001786 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001787 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001788 goto failed;
1789 }
1790
1791 val = !!cp->val;
1792
1793 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1794 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1795 goto failed;
1796 }
1797
1798 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1799 if (!cmd) {
1800 err = -ENOMEM;
1801 goto failed;
1802 }
1803
1804 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1805 if (err < 0) {
1806 mgmt_pending_remove(cmd);
1807 goto failed;
1808 }
1809
1810failed:
1811 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001812 return err;
1813}
1814
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001815static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001816{
1817 struct mgmt_mode *cp = data;
1818 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001819 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001820 int err;
1821
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001822 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001823
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001824 status = mgmt_bredr_support(hdev);
1825 if (status)
1826 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1827
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001828 if (!lmp_ssp_capable(hdev))
1829 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1830 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001831
Johan Hedberga7e80f22013-01-09 16:05:19 +02001832 if (cp->val != 0x00 && cp->val != 0x01)
1833 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1834 MGMT_STATUS_INVALID_PARAMS);
1835
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001836 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001837
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001838 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001839 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001840
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001841 if (cp->val) {
1842 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1843 &hdev->dev_flags);
1844 } else {
1845 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1846 &hdev->dev_flags);
1847 if (!changed)
1848 changed = test_and_clear_bit(HCI_HS_ENABLED,
1849 &hdev->dev_flags);
1850 else
1851 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001852 }
1853
1854 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1855 if (err < 0)
1856 goto failed;
1857
1858 if (changed)
1859 err = new_settings(hdev, sk);
1860
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001861 goto failed;
1862 }
1863
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001864 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1865 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001866 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1867 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001868 goto failed;
1869 }
1870
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001871 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001872 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1873 goto failed;
1874 }
1875
1876 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1877 if (!cmd) {
1878 err = -ENOMEM;
1879 goto failed;
1880 }
1881
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001882 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001883 if (err < 0) {
1884 mgmt_pending_remove(cmd);
1885 goto failed;
1886 }
1887
1888failed:
1889 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001890 return err;
1891}
1892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001893static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001894{
1895 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001896 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001897 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001898 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001899
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001900 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001901
Johan Hedberge6fe7982013-10-02 15:45:22 +03001902 status = mgmt_bredr_support(hdev);
1903 if (status)
1904 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001905
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001906 if (!lmp_ssp_capable(hdev))
1907 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1908 MGMT_STATUS_NOT_SUPPORTED);
1909
1910 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1911 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1912 MGMT_STATUS_REJECTED);
1913
Johan Hedberga7e80f22013-01-09 16:05:19 +02001914 if (cp->val != 0x00 && cp->val != 0x01)
1915 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1916 MGMT_STATUS_INVALID_PARAMS);
1917
Marcel Holtmannee392692013-10-01 22:59:23 -07001918 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001919
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001920 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001921 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001922 } else {
1923 if (hdev_is_powered(hdev)) {
1924 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1925 MGMT_STATUS_REJECTED);
1926 goto unlock;
1927 }
1928
Marcel Holtmannee392692013-10-01 22:59:23 -07001929 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001930 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001931
1932 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1933 if (err < 0)
1934 goto unlock;
1935
1936 if (changed)
1937 err = new_settings(hdev, sk);
1938
1939unlock:
1940 hci_dev_unlock(hdev);
1941 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001942}
1943
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001944static void le_enable_complete(struct hci_dev *hdev, u8 status)
1945{
1946 struct cmd_lookup match = { NULL, hdev };
1947
1948 if (status) {
1949 u8 mgmt_err = mgmt_status(status);
1950
1951 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1952 &mgmt_err);
1953 return;
1954 }
1955
1956 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1957
1958 new_settings(hdev, match.sk);
1959
1960 if (match.sk)
1961 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001962
1963 /* Make sure the controller has a good default for
1964 * advertising data. Restrict the update to when LE
1965 * has actually been enabled. During power on, the
1966 * update in powered_update_hci will take care of it.
1967 */
1968 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1969 struct hci_request req;
1970
1971 hci_dev_lock(hdev);
1972
1973 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001974 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001975 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001976 hci_req_run(&req, NULL);
1977
1978 hci_dev_unlock(hdev);
1979 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001980}
1981
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001982static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001983{
1984 struct mgmt_mode *cp = data;
1985 struct hci_cp_write_le_host_supported hci_cp;
1986 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001987 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001988 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001989 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001990
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001991 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001992
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001993 if (!lmp_le_capable(hdev))
1994 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1995 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001996
Johan Hedberga7e80f22013-01-09 16:05:19 +02001997 if (cp->val != 0x00 && cp->val != 0x01)
1998 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1999 MGMT_STATUS_INVALID_PARAMS);
2000
Johan Hedbergc73eee92013-04-19 18:35:21 +03002001 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002002 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002003 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2004 MGMT_STATUS_REJECTED);
2005
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002006 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002007
2008 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002009 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002011 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012 bool changed = false;
2013
2014 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2015 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2016 changed = true;
2017 }
2018
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002019 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2020 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002021 changed = true;
2022 }
2023
Johan Hedberg06199cf2012-02-22 16:37:11 +02002024 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2025 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002026 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002027
2028 if (changed)
2029 err = new_settings(hdev, sk);
2030
Johan Hedberg1de028c2012-02-29 19:55:35 -08002031 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002032 }
2033
Johan Hedberg4375f102013-09-25 13:26:10 +03002034 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2035 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002038 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002039 }
2040
2041 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2042 if (!cmd) {
2043 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002044 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002045 }
2046
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002047 hci_req_init(&req, hdev);
2048
Johan Hedberg06199cf2012-02-22 16:37:11 +02002049 memset(&hci_cp, 0, sizeof(hci_cp));
2050
2051 if (val) {
2052 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002053 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002054 } else {
2055 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2056 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002057 }
2058
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002059 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2060 &hci_cp);
2061
2062 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302063 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002064 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002065
Johan Hedberg1de028c2012-02-29 19:55:35 -08002066unlock:
2067 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002068 return err;
2069}
2070
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002071/* This is a helper function to test for pending mgmt commands that can
2072 * cause CoD or EIR HCI commands. We can only allow one such pending
2073 * mgmt command at a time since otherwise we cannot easily track what
2074 * the current values are, will be, and based on that calculate if a new
2075 * HCI command needs to be sent and if yes with what value.
2076 */
2077static bool pending_eir_or_class(struct hci_dev *hdev)
2078{
2079 struct pending_cmd *cmd;
2080
2081 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2082 switch (cmd->opcode) {
2083 case MGMT_OP_ADD_UUID:
2084 case MGMT_OP_REMOVE_UUID:
2085 case MGMT_OP_SET_DEV_CLASS:
2086 case MGMT_OP_SET_POWERED:
2087 return true;
2088 }
2089 }
2090
2091 return false;
2092}
2093
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002094static const u8 bluetooth_base_uuid[] = {
2095 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2096 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2097};
2098
2099static u8 get_uuid_size(const u8 *uuid)
2100{
2101 u32 val;
2102
2103 if (memcmp(uuid, bluetooth_base_uuid, 12))
2104 return 128;
2105
2106 val = get_unaligned_le32(&uuid[12]);
2107 if (val > 0xffff)
2108 return 32;
2109
2110 return 16;
2111}
2112
Johan Hedberg92da6092013-03-15 17:06:55 -05002113static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2114{
2115 struct pending_cmd *cmd;
2116
2117 hci_dev_lock(hdev);
2118
2119 cmd = mgmt_pending_find(mgmt_op, hdev);
2120 if (!cmd)
2121 goto unlock;
2122
2123 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2124 hdev->dev_class, 3);
2125
2126 mgmt_pending_remove(cmd);
2127
2128unlock:
2129 hci_dev_unlock(hdev);
2130}
2131
2132static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2133{
2134 BT_DBG("status 0x%02x", status);
2135
2136 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2137}
2138
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002139static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002140{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002141 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002142 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002143 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002144 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002145 int err;
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002148
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002149 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002150
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002151 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002152 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002153 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002154 goto failed;
2155 }
2156
Andre Guedes92c4c202012-06-07 19:05:44 -03002157 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002158 if (!uuid) {
2159 err = -ENOMEM;
2160 goto failed;
2161 }
2162
2163 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002164 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002165 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166
Johan Hedbergde66aa62013-01-27 00:31:27 +02002167 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002168
Johan Hedberg890ea892013-03-15 17:06:52 -05002169 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002170
Johan Hedberg890ea892013-03-15 17:06:52 -05002171 update_class(&req);
2172 update_eir(&req);
2173
Johan Hedberg92da6092013-03-15 17:06:55 -05002174 err = hci_req_run(&req, add_uuid_complete);
2175 if (err < 0) {
2176 if (err != -ENODATA)
2177 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002179 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002180 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002181 goto failed;
2182 }
2183
2184 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002185 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002186 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002187 goto failed;
2188 }
2189
2190 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002191
2192failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002193 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002194 return err;
2195}
2196
Johan Hedberg24b78d02012-02-23 23:24:30 +02002197static bool enable_service_cache(struct hci_dev *hdev)
2198{
2199 if (!hdev_is_powered(hdev))
2200 return false;
2201
2202 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002203 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2204 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002205 return true;
2206 }
2207
2208 return false;
2209}
2210
Johan Hedberg92da6092013-03-15 17:06:55 -05002211static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2212{
2213 BT_DBG("status 0x%02x", status);
2214
2215 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2216}
2217
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002218static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002219 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002220{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002221 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002222 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002223 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002224 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 -05002225 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002226 int err, found;
2227
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002228 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002229
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002230 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002231
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002232 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002233 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002234 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002235 goto unlock;
2236 }
2237
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002238 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002239 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002240
Johan Hedberg24b78d02012-02-23 23:24:30 +02002241 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002242 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002243 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002244 goto unlock;
2245 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002246
Johan Hedberg9246a862012-02-23 21:33:16 +02002247 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002248 }
2249
2250 found = 0;
2251
Johan Hedberg056341c2013-01-27 00:31:30 +02002252 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2254 continue;
2255
2256 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002257 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002258 found++;
2259 }
2260
2261 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002262 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002263 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002264 goto unlock;
2265 }
2266
Johan Hedberg9246a862012-02-23 21:33:16 +02002267update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002268 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002269
Johan Hedberg890ea892013-03-15 17:06:52 -05002270 update_class(&req);
2271 update_eir(&req);
2272
Johan Hedberg92da6092013-03-15 17:06:55 -05002273 err = hci_req_run(&req, remove_uuid_complete);
2274 if (err < 0) {
2275 if (err != -ENODATA)
2276 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002277
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002278 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002279 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002280 goto unlock;
2281 }
2282
2283 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002284 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002285 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002286 goto unlock;
2287 }
2288
2289 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002290
2291unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002292 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002293 return err;
2294}
2295
Johan Hedberg92da6092013-03-15 17:06:55 -05002296static void set_class_complete(struct hci_dev *hdev, u8 status)
2297{
2298 BT_DBG("status 0x%02x", status);
2299
2300 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2301}
2302
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002303static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002304 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002305{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002306 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002307 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002308 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002309 int err;
2310
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002311 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002312
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002313 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002314 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2315 MGMT_STATUS_NOT_SUPPORTED);
2316
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002317 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002318
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002319 if (pending_eir_or_class(hdev)) {
2320 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2321 MGMT_STATUS_BUSY);
2322 goto unlock;
2323 }
2324
2325 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2326 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2327 MGMT_STATUS_INVALID_PARAMS);
2328 goto unlock;
2329 }
2330
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331 hdev->major_class = cp->major;
2332 hdev->minor_class = cp->minor;
2333
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002334 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002335 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002336 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002337 goto unlock;
2338 }
2339
Johan Hedberg890ea892013-03-15 17:06:52 -05002340 hci_req_init(&req, hdev);
2341
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002342 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002343 hci_dev_unlock(hdev);
2344 cancel_delayed_work_sync(&hdev->service_cache);
2345 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002346 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002347 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002348
Johan Hedberg890ea892013-03-15 17:06:52 -05002349 update_class(&req);
2350
Johan Hedberg92da6092013-03-15 17:06:55 -05002351 err = hci_req_run(&req, set_class_complete);
2352 if (err < 0) {
2353 if (err != -ENODATA)
2354 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002355
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002356 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002357 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002358 goto unlock;
2359 }
2360
2361 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002363 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002364 goto unlock;
2365 }
2366
2367 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002368
Johan Hedbergb5235a62012-02-21 14:32:24 +02002369unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002370 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002371 return err;
2372}
2373
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002374static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002375 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002376{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002377 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002378 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002379 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002380 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002381
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002382 BT_DBG("request for %s", hdev->name);
2383
2384 if (!lmp_bredr_capable(hdev))
2385 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2386 MGMT_STATUS_NOT_SUPPORTED);
2387
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002388 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002389
Johan Hedberg86742e12011-11-07 23:13:38 +02002390 expected_len = sizeof(*cp) + key_count *
2391 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002392 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002393 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002394 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002396 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002397 }
2398
Johan Hedberg4ae14302013-01-20 14:27:13 +02002399 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2400 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2401 MGMT_STATUS_INVALID_PARAMS);
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002404 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002405
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002406 for (i = 0; i < key_count; i++) {
2407 struct mgmt_link_key_info *key = &cp->keys[i];
2408
Marcel Holtmann8e991132014-01-10 02:07:25 -08002409 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002410 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2411 MGMT_STATUS_INVALID_PARAMS);
2412 }
2413
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002414 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002415
2416 hci_link_keys_clear(hdev);
2417
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002418 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002419 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002420 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002421 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2422
2423 if (changed)
2424 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002425
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002426 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002427 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002428
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002429 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002430 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002431 }
2432
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002433 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002434
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002435 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002436
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002437 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002438}
2439
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002440static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002441 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002442{
2443 struct mgmt_ev_device_unpaired ev;
2444
2445 bacpy(&ev.addr.bdaddr, bdaddr);
2446 ev.addr.type = addr_type;
2447
2448 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002449 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002450}
2451
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002452static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002453 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002454{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002455 struct mgmt_cp_unpair_device *cp = data;
2456 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002457 struct hci_cp_disconnect dc;
2458 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002459 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002460 int err;
2461
Johan Hedberga8a1d192011-11-10 15:54:38 +02002462 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002463 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2464 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002465
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002466 if (!bdaddr_type_is_valid(cp->addr.type))
2467 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2468 MGMT_STATUS_INVALID_PARAMS,
2469 &rp, sizeof(rp));
2470
Johan Hedberg118da702013-01-20 14:27:20 +02002471 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2472 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2473 MGMT_STATUS_INVALID_PARAMS,
2474 &rp, sizeof(rp));
2475
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002476 hci_dev_lock(hdev);
2477
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002478 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002479 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002480 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002481 goto unlock;
2482 }
2483
Johan Hedberge0b2b272014-02-18 17:14:31 +02002484 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002485 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002486 } else {
2487 u8 addr_type;
2488
2489 if (cp->addr.type == BDADDR_LE_PUBLIC)
2490 addr_type = ADDR_LE_DEV_PUBLIC;
2491 else
2492 addr_type = ADDR_LE_DEV_RANDOM;
2493
Johan Hedberga7ec7332014-02-18 17:14:35 +02002494 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2495
Andre Guedesa9b0a042014-02-26 20:21:52 -03002496 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2497
Johan Hedberge0b2b272014-02-18 17:14:31 +02002498 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2499 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002500
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002501 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002502 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002503 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002504 goto unlock;
2505 }
2506
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002507 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002508 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002509 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002510 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002511 else
2512 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002513 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002514 } else {
2515 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002516 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002517
Johan Hedberga8a1d192011-11-10 15:54:38 +02002518 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002520 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002521 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002522 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002523 }
2524
Johan Hedberg124f6e32012-02-09 13:50:12 +02002525 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002526 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002527 if (!cmd) {
2528 err = -ENOMEM;
2529 goto unlock;
2530 }
2531
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002532 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002533 dc.reason = 0x13; /* Remote User Terminated Connection */
2534 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2535 if (err < 0)
2536 mgmt_pending_remove(cmd);
2537
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002538unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002539 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002540 return err;
2541}
2542
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002543static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002544 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002545{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002546 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002547 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002548 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002549 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002550 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002551 int err;
2552
2553 BT_DBG("");
2554
Johan Hedberg06a63b12013-01-20 14:27:21 +02002555 memset(&rp, 0, sizeof(rp));
2556 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2557 rp.addr.type = cp->addr.type;
2558
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002559 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002560 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2561 MGMT_STATUS_INVALID_PARAMS,
2562 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002563
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002564 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002565
2566 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002567 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2568 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002569 goto failed;
2570 }
2571
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002572 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002573 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2574 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575 goto failed;
2576 }
2577
Andre Guedes591f47f2012-04-24 21:02:49 -03002578 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002579 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2580 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002581 else
2582 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002583
Vishal Agarwalf9607272012-06-13 05:32:43 +05302584 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002585 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2586 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002587 goto failed;
2588 }
2589
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002590 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002591 if (!cmd) {
2592 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002593 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002594 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002595
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002596 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002597 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002598
2599 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2600 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002601 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002602
2603failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002604 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002605 return err;
2606}
2607
Andre Guedes57c14772012-04-24 21:02:50 -03002608static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002609{
2610 switch (link_type) {
2611 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002612 switch (addr_type) {
2613 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002614 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002615
Johan Hedberg48264f02011-11-09 13:58:58 +02002616 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002617 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002618 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002619 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002620
Johan Hedberg4c659c32011-11-07 23:13:39 +02002621 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002622 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002623 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002624 }
2625}
2626
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002627static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2628 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002629{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002630 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002631 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002632 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002633 int err;
2634 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002635
2636 BT_DBG("");
2637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002638 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002639
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002640 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002641 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002642 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002643 goto unlock;
2644 }
2645
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002646 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002647 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2648 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002649 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002650 }
2651
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002652 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002653 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002654 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002655 err = -ENOMEM;
2656 goto unlock;
2657 }
2658
Johan Hedberg2784eb42011-01-21 13:56:35 +02002659 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002660 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002661 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2662 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002663 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002664 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002665 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002666 continue;
2667 i++;
2668 }
2669
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002670 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002671
Johan Hedberg4c659c32011-11-07 23:13:39 +02002672 /* Recalculate length in case of filtered SCO connections, etc */
2673 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002674
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002675 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002676 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002677
Johan Hedberga38528f2011-01-22 06:46:43 +02002678 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002679
2680unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002681 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002682 return err;
2683}
2684
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002685static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002686 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002687{
2688 struct pending_cmd *cmd;
2689 int err;
2690
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002691 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002692 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002693 if (!cmd)
2694 return -ENOMEM;
2695
Johan Hedbergd8457692012-02-17 14:24:57 +02002696 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002697 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002698 if (err < 0)
2699 mgmt_pending_remove(cmd);
2700
2701 return err;
2702}
2703
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002704static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002705 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002706{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002707 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002708 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002709 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002710 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002711 int err;
2712
2713 BT_DBG("");
2714
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002715 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002716
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002717 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002718 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002719 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002720 goto failed;
2721 }
2722
Johan Hedbergd8457692012-02-17 14:24:57 +02002723 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002724 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002725 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002727 goto failed;
2728 }
2729
2730 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002731 struct mgmt_cp_pin_code_neg_reply ncp;
2732
2733 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002734
2735 BT_ERR("PIN code is not 16 bytes long");
2736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002737 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002738 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002739 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002740 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002741
2742 goto failed;
2743 }
2744
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002745 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002746 if (!cmd) {
2747 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002748 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002749 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002750
Johan Hedbergd8457692012-02-17 14:24:57 +02002751 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002752 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002753 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002754
2755 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2756 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002757 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002758
2759failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002760 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002761 return err;
2762}
2763
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002764static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2765 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002766{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002767 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002768
2769 BT_DBG("");
2770
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002771 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002772
2773 hdev->io_capability = cp->io_capability;
2774
2775 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002776 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002777
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002778 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002779
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002780 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2781 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002782}
2783
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002784static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002785{
2786 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002787 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002788
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002789 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002790 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2791 continue;
2792
Johan Hedberge9a416b2011-02-19 12:05:56 -03002793 if (cmd->user_data != conn)
2794 continue;
2795
2796 return cmd;
2797 }
2798
2799 return NULL;
2800}
2801
2802static void pairing_complete(struct pending_cmd *cmd, u8 status)
2803{
2804 struct mgmt_rp_pair_device rp;
2805 struct hci_conn *conn = cmd->user_data;
2806
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002807 bacpy(&rp.addr.bdaddr, &conn->dst);
2808 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002809
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002810 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002811 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002812
2813 /* So we don't get further callbacks for this connection */
2814 conn->connect_cfm_cb = NULL;
2815 conn->security_cfm_cb = NULL;
2816 conn->disconn_cfm_cb = NULL;
2817
David Herrmann76a68ba2013-04-06 20:28:37 +02002818 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002819
Johan Hedberga664b5b2011-02-19 12:06:02 -03002820 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002821}
2822
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002823void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2824{
2825 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2826 struct pending_cmd *cmd;
2827
2828 cmd = find_pairing(conn);
2829 if (cmd)
2830 pairing_complete(cmd, status);
2831}
2832
Johan Hedberge9a416b2011-02-19 12:05:56 -03002833static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2834{
2835 struct pending_cmd *cmd;
2836
2837 BT_DBG("status %u", status);
2838
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002839 cmd = find_pairing(conn);
2840 if (!cmd)
2841 BT_DBG("Unable to find a pending command");
2842 else
Johan Hedberge2113262012-02-18 15:20:03 +02002843 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002844}
2845
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002846static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302847{
2848 struct pending_cmd *cmd;
2849
2850 BT_DBG("status %u", status);
2851
2852 if (!status)
2853 return;
2854
2855 cmd = find_pairing(conn);
2856 if (!cmd)
2857 BT_DBG("Unable to find a pending command");
2858 else
2859 pairing_complete(cmd, mgmt_status(status));
2860}
2861
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002862static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002863 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002864{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002865 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002866 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002867 struct pending_cmd *cmd;
2868 u8 sec_level, auth_type;
2869 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002870 int err;
2871
2872 BT_DBG("");
2873
Szymon Jancf950a30e2013-01-18 12:48:07 +01002874 memset(&rp, 0, sizeof(rp));
2875 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2876 rp.addr.type = cp->addr.type;
2877
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002878 if (!bdaddr_type_is_valid(cp->addr.type))
2879 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2880 MGMT_STATUS_INVALID_PARAMS,
2881 &rp, sizeof(rp));
2882
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002883 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002884
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002885 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002886 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2887 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002888 goto unlock;
2889 }
2890
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002891 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002892 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002893
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002894 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002895 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2896 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002897 } else {
2898 u8 addr_type;
2899
2900 /* Convert from L2CAP channel address type to HCI address type
2901 */
2902 if (cp->addr.type == BDADDR_LE_PUBLIC)
2903 addr_type = ADDR_LE_DEV_PUBLIC;
2904 else
2905 addr_type = ADDR_LE_DEV_RANDOM;
2906
2907 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002908 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002909 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002910
Ville Tervo30e76272011-02-22 16:10:53 -03002911 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002912 int status;
2913
2914 if (PTR_ERR(conn) == -EBUSY)
2915 status = MGMT_STATUS_BUSY;
2916 else
2917 status = MGMT_STATUS_CONNECT_FAILED;
2918
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002919 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002920 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002921 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002922 goto unlock;
2923 }
2924
2925 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002926 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002927 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002928 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002929 goto unlock;
2930 }
2931
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002932 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002933 if (!cmd) {
2934 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002935 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002936 goto unlock;
2937 }
2938
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002939 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002940 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002941 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002942 conn->security_cfm_cb = pairing_complete_cb;
2943 conn->disconn_cfm_cb = pairing_complete_cb;
2944 } else {
2945 conn->connect_cfm_cb = le_pairing_complete_cb;
2946 conn->security_cfm_cb = le_pairing_complete_cb;
2947 conn->disconn_cfm_cb = le_pairing_complete_cb;
2948 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002949
Johan Hedberge9a416b2011-02-19 12:05:56 -03002950 conn->io_capability = cp->io_cap;
2951 cmd->user_data = conn;
2952
2953 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002954 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002955 pairing_complete(cmd, 0);
2956
2957 err = 0;
2958
2959unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002960 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002961 return err;
2962}
2963
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2965 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002966{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002967 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002968 struct pending_cmd *cmd;
2969 struct hci_conn *conn;
2970 int err;
2971
2972 BT_DBG("");
2973
Johan Hedberg28424702012-02-02 04:02:29 +02002974 hci_dev_lock(hdev);
2975
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002976 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002979 goto unlock;
2980 }
2981
Johan Hedberg28424702012-02-02 04:02:29 +02002982 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2983 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002984 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002986 goto unlock;
2987 }
2988
2989 conn = cmd->user_data;
2990
2991 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002992 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002993 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002994 goto unlock;
2995 }
2996
2997 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2998
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002999 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003001unlock:
3002 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003003 return err;
3004}
3005
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003006static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003007 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003008 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003009{
Johan Hedberga5c29682011-02-19 12:05:57 -03003010 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003011 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003012 int err;
3013
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003014 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003016 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003017 err = cmd_complete(sk, hdev->id, mgmt_op,
3018 MGMT_STATUS_NOT_POWERED, addr,
3019 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003020 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003021 }
3022
Johan Hedberg1707c602013-03-15 17:07:15 -05003023 if (addr->type == BDADDR_BREDR)
3024 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003025 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003026 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003027
Johan Hedberg272d90d2012-02-09 15:26:12 +02003028 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003029 err = cmd_complete(sk, hdev->id, mgmt_op,
3030 MGMT_STATUS_NOT_CONNECTED, addr,
3031 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003032 goto done;
3033 }
3034
Johan Hedberg1707c602013-03-15 17:07:15 -05003035 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08003036 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08003037 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08003038
Brian Gix5fe57d92011-12-21 16:12:13 -08003039 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003040 err = cmd_complete(sk, hdev->id, mgmt_op,
3041 MGMT_STATUS_SUCCESS, addr,
3042 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003043 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003044 err = cmd_complete(sk, hdev->id, mgmt_op,
3045 MGMT_STATUS_FAILED, addr,
3046 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003047
Brian Gix47c15e22011-11-16 13:53:14 -08003048 goto done;
3049 }
3050
Johan Hedberg1707c602013-03-15 17:07:15 -05003051 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003052 if (!cmd) {
3053 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003054 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003055 }
3056
Brian Gix0df4c182011-11-16 13:53:13 -08003057 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003058 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3059 struct hci_cp_user_passkey_reply cp;
3060
Johan Hedberg1707c602013-03-15 17:07:15 -05003061 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003062 cp.passkey = passkey;
3063 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3064 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003065 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3066 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003067
Johan Hedberga664b5b2011-02-19 12:06:02 -03003068 if (err < 0)
3069 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003070
Brian Gix0df4c182011-11-16 13:53:13 -08003071done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003072 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003073 return err;
3074}
3075
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303076static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3077 void *data, u16 len)
3078{
3079 struct mgmt_cp_pin_code_neg_reply *cp = data;
3080
3081 BT_DBG("");
3082
Johan Hedberg1707c602013-03-15 17:07:15 -05003083 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303084 MGMT_OP_PIN_CODE_NEG_REPLY,
3085 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3086}
3087
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003088static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3089 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003090{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003091 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003092
3093 BT_DBG("");
3094
3095 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003096 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003097 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003098
Johan Hedberg1707c602013-03-15 17:07:15 -05003099 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003100 MGMT_OP_USER_CONFIRM_REPLY,
3101 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003102}
3103
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003104static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003105 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003106{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003107 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003108
3109 BT_DBG("");
3110
Johan Hedberg1707c602013-03-15 17:07:15 -05003111 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003112 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3113 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003114}
3115
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003116static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3117 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003118{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003119 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003120
3121 BT_DBG("");
3122
Johan Hedberg1707c602013-03-15 17:07:15 -05003123 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003124 MGMT_OP_USER_PASSKEY_REPLY,
3125 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003126}
3127
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003128static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003130{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003131 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003132
3133 BT_DBG("");
3134
Johan Hedberg1707c602013-03-15 17:07:15 -05003135 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3137 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003138}
3139
Johan Hedberg13928972013-03-15 17:07:00 -05003140static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003141{
Johan Hedberg13928972013-03-15 17:07:00 -05003142 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003143 struct hci_cp_write_local_name cp;
3144
Johan Hedberg13928972013-03-15 17:07:00 -05003145 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003146
Johan Hedberg890ea892013-03-15 17:06:52 -05003147 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003148}
3149
Johan Hedberg13928972013-03-15 17:07:00 -05003150static void set_name_complete(struct hci_dev *hdev, u8 status)
3151{
3152 struct mgmt_cp_set_local_name *cp;
3153 struct pending_cmd *cmd;
3154
3155 BT_DBG("status 0x%02x", status);
3156
3157 hci_dev_lock(hdev);
3158
3159 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3160 if (!cmd)
3161 goto unlock;
3162
3163 cp = cmd->param;
3164
3165 if (status)
3166 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3167 mgmt_status(status));
3168 else
3169 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3170 cp, sizeof(*cp));
3171
3172 mgmt_pending_remove(cmd);
3173
3174unlock:
3175 hci_dev_unlock(hdev);
3176}
3177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003178static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003180{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003181 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003182 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003183 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003184 int err;
3185
3186 BT_DBG("");
3187
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003188 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003189
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003190 /* If the old values are the same as the new ones just return a
3191 * direct command complete event.
3192 */
3193 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3194 !memcmp(hdev->short_name, cp->short_name,
3195 sizeof(hdev->short_name))) {
3196 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3197 data, len);
3198 goto failed;
3199 }
3200
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003201 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003202
Johan Hedbergb5235a62012-02-21 14:32:24 +02003203 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003204 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003205
3206 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003207 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003208 if (err < 0)
3209 goto failed;
3210
3211 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003212 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003213
Johan Hedbergb5235a62012-02-21 14:32:24 +02003214 goto failed;
3215 }
3216
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003217 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003218 if (!cmd) {
3219 err = -ENOMEM;
3220 goto failed;
3221 }
3222
Johan Hedberg13928972013-03-15 17:07:00 -05003223 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3224
Johan Hedberg890ea892013-03-15 17:06:52 -05003225 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003226
3227 if (lmp_bredr_capable(hdev)) {
3228 update_name(&req);
3229 update_eir(&req);
3230 }
3231
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003232 /* The name is stored in the scan response data and so
3233 * no need to udpate the advertising data here.
3234 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003235 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003236 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003237
Johan Hedberg13928972013-03-15 17:07:00 -05003238 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003239 if (err < 0)
3240 mgmt_pending_remove(cmd);
3241
3242failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003243 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003244 return err;
3245}
3246
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003247static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003248 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003249{
Szymon Jancc35938b2011-03-22 13:12:21 +01003250 struct pending_cmd *cmd;
3251 int err;
3252
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003253 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003254
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003255 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003256
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003257 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003260 goto unlock;
3261 }
3262
Andre Guedes9a1a1992012-07-24 15:03:48 -03003263 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003264 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003265 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003266 goto unlock;
3267 }
3268
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003269 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003270 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003271 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003272 goto unlock;
3273 }
3274
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003275 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003276 if (!cmd) {
3277 err = -ENOMEM;
3278 goto unlock;
3279 }
3280
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003281 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3282 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3283 0, NULL);
3284 else
3285 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3286
Szymon Jancc35938b2011-03-22 13:12:21 +01003287 if (err < 0)
3288 mgmt_pending_remove(cmd);
3289
3290unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003291 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003292 return err;
3293}
3294
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003295static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003297{
Szymon Janc2763eda2011-03-22 13:12:22 +01003298 int err;
3299
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003300 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003301
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003302 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003303
Marcel Holtmannec109112014-01-10 02:07:30 -08003304 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3305 struct mgmt_cp_add_remote_oob_data *cp = data;
3306 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003307
Marcel Holtmannec109112014-01-10 02:07:30 -08003308 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3309 cp->hash, cp->randomizer);
3310 if (err < 0)
3311 status = MGMT_STATUS_FAILED;
3312 else
3313 status = MGMT_STATUS_SUCCESS;
3314
3315 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3316 status, &cp->addr, sizeof(cp->addr));
3317 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3318 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3319 u8 status;
3320
3321 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3322 cp->hash192,
3323 cp->randomizer192,
3324 cp->hash256,
3325 cp->randomizer256);
3326 if (err < 0)
3327 status = MGMT_STATUS_FAILED;
3328 else
3329 status = MGMT_STATUS_SUCCESS;
3330
3331 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3332 status, &cp->addr, sizeof(cp->addr));
3333 } else {
3334 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3335 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3336 MGMT_STATUS_INVALID_PARAMS);
3337 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003338
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003339 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003340 return err;
3341}
3342
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003343static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003344 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003345{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003346 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003347 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003348 int err;
3349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003350 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003351
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003352 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003353
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003354 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003355 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003356 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003357 else
Szymon Janca6785be2012-12-13 15:11:21 +01003358 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003359
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003360 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003361 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003362
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003363 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003364 return err;
3365}
3366
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003367static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3368{
3369 struct pending_cmd *cmd;
3370 u8 type;
3371 int err;
3372
3373 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3374
3375 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3376 if (!cmd)
3377 return -ENOENT;
3378
3379 type = hdev->discovery.type;
3380
3381 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3382 &type, sizeof(type));
3383 mgmt_pending_remove(cmd);
3384
3385 return err;
3386}
3387
Andre Guedes7c307722013-04-30 15:29:28 -03003388static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3389{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003390 unsigned long timeout = 0;
3391
Andre Guedes7c307722013-04-30 15:29:28 -03003392 BT_DBG("status %d", status);
3393
3394 if (status) {
3395 hci_dev_lock(hdev);
3396 mgmt_start_discovery_failed(hdev, status);
3397 hci_dev_unlock(hdev);
3398 return;
3399 }
3400
3401 hci_dev_lock(hdev);
3402 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3403 hci_dev_unlock(hdev);
3404
3405 switch (hdev->discovery.type) {
3406 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003407 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003408 break;
3409
3410 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003411 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003412 break;
3413
3414 case DISCOV_TYPE_BREDR:
3415 break;
3416
3417 default:
3418 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3419 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003420
3421 if (!timeout)
3422 return;
3423
3424 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003425}
3426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003427static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003428 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003429{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003430 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003431 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003432 struct hci_cp_le_set_scan_param param_cp;
3433 struct hci_cp_le_set_scan_enable enable_cp;
3434 struct hci_cp_inquiry inq_cp;
3435 struct hci_request req;
3436 /* General inquiry access code (GIAC) */
3437 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003438 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003439 int err;
3440
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003441 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003442
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003443 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003444
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003445 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003446 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003447 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003448 goto failed;
3449 }
3450
Andre Guedes642be6c2012-03-21 00:03:37 -03003451 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3452 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3453 MGMT_STATUS_BUSY);
3454 goto failed;
3455 }
3456
Johan Hedbergff9ef572012-01-04 14:23:45 +02003457 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003458 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003459 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003460 goto failed;
3461 }
3462
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003463 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003464 if (!cmd) {
3465 err = -ENOMEM;
3466 goto failed;
3467 }
3468
Andre Guedes4aab14e2012-02-17 20:39:36 -03003469 hdev->discovery.type = cp->type;
3470
Andre Guedes7c307722013-04-30 15:29:28 -03003471 hci_req_init(&req, hdev);
3472
Andre Guedes4aab14e2012-02-17 20:39:36 -03003473 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003474 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003475 status = mgmt_bredr_support(hdev);
3476 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003477 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003478 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003479 mgmt_pending_remove(cmd);
3480 goto failed;
3481 }
3482
Andre Guedes7c307722013-04-30 15:29:28 -03003483 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3484 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3485 MGMT_STATUS_BUSY);
3486 mgmt_pending_remove(cmd);
3487 goto failed;
3488 }
3489
3490 hci_inquiry_cache_flush(hdev);
3491
3492 memset(&inq_cp, 0, sizeof(inq_cp));
3493 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003494 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003495 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003496 break;
3497
3498 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003499 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003500 status = mgmt_le_support(hdev);
3501 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003502 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003503 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003504 mgmt_pending_remove(cmd);
3505 goto failed;
3506 }
3507
Andre Guedes7c307722013-04-30 15:29:28 -03003508 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003509 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003510 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3511 MGMT_STATUS_NOT_SUPPORTED);
3512 mgmt_pending_remove(cmd);
3513 goto failed;
3514 }
3515
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003516 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003517 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3518 MGMT_STATUS_REJECTED);
3519 mgmt_pending_remove(cmd);
3520 goto failed;
3521 }
3522
Andre Guedesc54c3862014-02-26 20:21:50 -03003523 /* If controller is scanning, it means the background scanning
3524 * is running. Thus, we should temporarily stop it in order to
3525 * set the discovery scanning parameters.
3526 */
3527 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3528 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003529
3530 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003531
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003532 /* All active scans will be done with either a resolvable
3533 * private address (when privacy feature has been enabled)
3534 * or unresolvable private address.
3535 */
3536 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003537 if (err < 0) {
3538 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3539 MGMT_STATUS_FAILED);
3540 mgmt_pending_remove(cmd);
3541 goto failed;
3542 }
3543
Andre Guedes7c307722013-04-30 15:29:28 -03003544 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003545 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3546 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003547 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003548 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3549 &param_cp);
3550
3551 memset(&enable_cp, 0, sizeof(enable_cp));
3552 enable_cp.enable = LE_SCAN_ENABLE;
3553 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3554 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3555 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003556 break;
3557
Andre Guedesf39799f2012-02-17 20:39:35 -03003558 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003559 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3560 MGMT_STATUS_INVALID_PARAMS);
3561 mgmt_pending_remove(cmd);
3562 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003563 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003564
Andre Guedes7c307722013-04-30 15:29:28 -03003565 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003566 if (err < 0)
3567 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003568 else
3569 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003570
3571failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003572 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003573 return err;
3574}
3575
Andre Guedes1183fdc2013-04-30 15:29:35 -03003576static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3577{
3578 struct pending_cmd *cmd;
3579 int err;
3580
3581 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3582 if (!cmd)
3583 return -ENOENT;
3584
3585 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3586 &hdev->discovery.type, sizeof(hdev->discovery.type));
3587 mgmt_pending_remove(cmd);
3588
3589 return err;
3590}
3591
Andre Guedes0e05bba2013-04-30 15:29:33 -03003592static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3593{
3594 BT_DBG("status %d", status);
3595
3596 hci_dev_lock(hdev);
3597
3598 if (status) {
3599 mgmt_stop_discovery_failed(hdev, status);
3600 goto unlock;
3601 }
3602
3603 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3604
3605unlock:
3606 hci_dev_unlock(hdev);
3607}
3608
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003609static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003610 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003611{
Johan Hedbergd9306502012-02-20 23:25:18 +02003612 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003613 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003614 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003615 int err;
3616
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003617 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003618
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003619 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003620
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003621 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003622 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003623 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3624 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003625 goto unlock;
3626 }
3627
3628 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003629 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3631 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003632 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003633 }
3634
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003635 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003636 if (!cmd) {
3637 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003638 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003639 }
3640
Andre Guedes0e05bba2013-04-30 15:29:33 -03003641 hci_req_init(&req, hdev);
3642
Johan Hedberg21a60d32014-06-10 14:05:58 +03003643 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003644
Johan Hedberg21a60d32014-06-10 14:05:58 +03003645 err = hci_req_run(&req, stop_discovery_complete);
3646 if (!err) {
3647 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003648 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003649 }
3650
Johan Hedberg21a60d32014-06-10 14:05:58 +03003651 mgmt_pending_remove(cmd);
3652
3653 /* If no HCI commands were sent we're done */
3654 if (err == -ENODATA) {
3655 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3656 &mgmt_cp->type, sizeof(mgmt_cp->type));
3657 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3658 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003659
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003660unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003661 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003662 return err;
3663}
3664
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003665static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003666 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003667{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003668 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003669 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003670 int err;
3671
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003672 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003673
Johan Hedberg561aafb2012-01-04 13:31:59 +02003674 hci_dev_lock(hdev);
3675
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003676 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003677 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3678 MGMT_STATUS_FAILED, &cp->addr,
3679 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003680 goto failed;
3681 }
3682
Johan Hedberga198e7b2012-02-17 14:27:06 +02003683 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003684 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003685 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3686 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3687 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003688 goto failed;
3689 }
3690
3691 if (cp->name_known) {
3692 e->name_state = NAME_KNOWN;
3693 list_del(&e->list);
3694 } else {
3695 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003696 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003697 }
3698
Johan Hedberge3846622013-01-09 15:29:33 +02003699 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3700 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003701
3702failed:
3703 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003704 return err;
3705}
3706
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003707static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003708 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003709{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003710 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003711 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003712 int err;
3713
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003714 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003715
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003716 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003717 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3718 MGMT_STATUS_INVALID_PARAMS,
3719 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003720
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003721 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003722
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003723 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003724 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003725 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003726 else
Szymon Janca6785be2012-12-13 15:11:21 +01003727 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003728
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003729 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003730 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003731
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003732 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003733
3734 return err;
3735}
3736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003737static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003738 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003739{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003740 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003741 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003742 int err;
3743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003744 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003745
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003746 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003747 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3748 MGMT_STATUS_INVALID_PARAMS,
3749 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003750
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003751 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003752
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003753 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003754 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003755 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003756 else
Szymon Janca6785be2012-12-13 15:11:21 +01003757 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003758
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003759 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003760 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003761
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003762 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003763
3764 return err;
3765}
3766
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003767static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3768 u16 len)
3769{
3770 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003771 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003772 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003773 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003774
3775 BT_DBG("%s", hdev->name);
3776
Szymon Jancc72d4b82012-03-16 16:02:57 +01003777 source = __le16_to_cpu(cp->source);
3778
3779 if (source > 0x0002)
3780 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3781 MGMT_STATUS_INVALID_PARAMS);
3782
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003783 hci_dev_lock(hdev);
3784
Szymon Jancc72d4b82012-03-16 16:02:57 +01003785 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003786 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3787 hdev->devid_product = __le16_to_cpu(cp->product);
3788 hdev->devid_version = __le16_to_cpu(cp->version);
3789
3790 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3791
Johan Hedberg890ea892013-03-15 17:06:52 -05003792 hci_req_init(&req, hdev);
3793 update_eir(&req);
3794 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003795
3796 hci_dev_unlock(hdev);
3797
3798 return err;
3799}
3800
Johan Hedberg4375f102013-09-25 13:26:10 +03003801static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3802{
3803 struct cmd_lookup match = { NULL, hdev };
3804
3805 if (status) {
3806 u8 mgmt_err = mgmt_status(status);
3807
3808 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3809 cmd_status_rsp, &mgmt_err);
3810 return;
3811 }
3812
3813 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3814 &match);
3815
3816 new_settings(hdev, match.sk);
3817
3818 if (match.sk)
3819 sock_put(match.sk);
3820}
3821
Marcel Holtmann21b51872013-10-10 09:47:53 -07003822static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3823 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003824{
3825 struct mgmt_mode *cp = data;
3826 struct pending_cmd *cmd;
3827 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003828 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003829 int err;
3830
3831 BT_DBG("request for %s", hdev->name);
3832
Johan Hedberge6fe7982013-10-02 15:45:22 +03003833 status = mgmt_le_support(hdev);
3834 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003835 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003836 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003837
3838 if (cp->val != 0x00 && cp->val != 0x01)
3839 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3840 MGMT_STATUS_INVALID_PARAMS);
3841
3842 hci_dev_lock(hdev);
3843
3844 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003845 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003846
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003847 /* The following conditions are ones which mean that we should
3848 * not do any HCI communication but directly send a mgmt
3849 * response to user space (after toggling the flag if
3850 * necessary).
3851 */
3852 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003853 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003854 bool changed = false;
3855
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003856 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3857 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003858 changed = true;
3859 }
3860
3861 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3862 if (err < 0)
3863 goto unlock;
3864
3865 if (changed)
3866 err = new_settings(hdev, sk);
3867
3868 goto unlock;
3869 }
3870
3871 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3872 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3873 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3874 MGMT_STATUS_BUSY);
3875 goto unlock;
3876 }
3877
3878 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3879 if (!cmd) {
3880 err = -ENOMEM;
3881 goto unlock;
3882 }
3883
3884 hci_req_init(&req, hdev);
3885
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003886 if (val)
3887 enable_advertising(&req);
3888 else
3889 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003890
3891 err = hci_req_run(&req, set_advertising_complete);
3892 if (err < 0)
3893 mgmt_pending_remove(cmd);
3894
3895unlock:
3896 hci_dev_unlock(hdev);
3897 return err;
3898}
3899
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003900static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3901 void *data, u16 len)
3902{
3903 struct mgmt_cp_set_static_address *cp = data;
3904 int err;
3905
3906 BT_DBG("%s", hdev->name);
3907
Marcel Holtmann62af4442013-10-02 22:10:32 -07003908 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003909 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003910 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003911
3912 if (hdev_is_powered(hdev))
3913 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3914 MGMT_STATUS_REJECTED);
3915
3916 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3917 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3918 return cmd_status(sk, hdev->id,
3919 MGMT_OP_SET_STATIC_ADDRESS,
3920 MGMT_STATUS_INVALID_PARAMS);
3921
3922 /* Two most significant bits shall be set */
3923 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3924 return cmd_status(sk, hdev->id,
3925 MGMT_OP_SET_STATIC_ADDRESS,
3926 MGMT_STATUS_INVALID_PARAMS);
3927 }
3928
3929 hci_dev_lock(hdev);
3930
3931 bacpy(&hdev->static_addr, &cp->bdaddr);
3932
3933 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3934
3935 hci_dev_unlock(hdev);
3936
3937 return err;
3938}
3939
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003940static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3941 void *data, u16 len)
3942{
3943 struct mgmt_cp_set_scan_params *cp = data;
3944 __u16 interval, window;
3945 int err;
3946
3947 BT_DBG("%s", hdev->name);
3948
3949 if (!lmp_le_capable(hdev))
3950 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3951 MGMT_STATUS_NOT_SUPPORTED);
3952
3953 interval = __le16_to_cpu(cp->interval);
3954
3955 if (interval < 0x0004 || interval > 0x4000)
3956 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3957 MGMT_STATUS_INVALID_PARAMS);
3958
3959 window = __le16_to_cpu(cp->window);
3960
3961 if (window < 0x0004 || window > 0x4000)
3962 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3963 MGMT_STATUS_INVALID_PARAMS);
3964
Marcel Holtmann899e1072013-10-14 09:55:32 -07003965 if (window > interval)
3966 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3967 MGMT_STATUS_INVALID_PARAMS);
3968
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003969 hci_dev_lock(hdev);
3970
3971 hdev->le_scan_interval = interval;
3972 hdev->le_scan_window = window;
3973
3974 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3975
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003976 /* If background scan is running, restart it so new parameters are
3977 * loaded.
3978 */
3979 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3980 hdev->discovery.state == DISCOVERY_STOPPED) {
3981 struct hci_request req;
3982
3983 hci_req_init(&req, hdev);
3984
3985 hci_req_add_le_scan_disable(&req);
3986 hci_req_add_le_passive_scan(&req);
3987
3988 hci_req_run(&req, NULL);
3989 }
3990
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003991 hci_dev_unlock(hdev);
3992
3993 return err;
3994}
3995
Johan Hedberg33e38b32013-03-15 17:07:05 -05003996static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3997{
3998 struct pending_cmd *cmd;
3999
4000 BT_DBG("status 0x%02x", status);
4001
4002 hci_dev_lock(hdev);
4003
4004 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4005 if (!cmd)
4006 goto unlock;
4007
4008 if (status) {
4009 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4010 mgmt_status(status));
4011 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004012 struct mgmt_mode *cp = cmd->param;
4013
4014 if (cp->val)
4015 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4016 else
4017 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4018
Johan Hedberg33e38b32013-03-15 17:07:05 -05004019 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4020 new_settings(hdev, cmd->sk);
4021 }
4022
4023 mgmt_pending_remove(cmd);
4024
4025unlock:
4026 hci_dev_unlock(hdev);
4027}
4028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004029static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004030 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004031{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004032 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004033 struct pending_cmd *cmd;
4034 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004035 int err;
4036
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004037 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004038
Johan Hedberg56f87902013-10-02 13:43:13 +03004039 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4040 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004041 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4042 MGMT_STATUS_NOT_SUPPORTED);
4043
Johan Hedberga7e80f22013-01-09 16:05:19 +02004044 if (cp->val != 0x00 && cp->val != 0x01)
4045 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4046 MGMT_STATUS_INVALID_PARAMS);
4047
Johan Hedberg5400c042012-02-21 16:40:33 +02004048 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004049 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004050 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004051
4052 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004053 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004054 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004055
4056 hci_dev_lock(hdev);
4057
Johan Hedberg05cbf292013-03-15 17:07:07 -05004058 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4059 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4060 MGMT_STATUS_BUSY);
4061 goto unlock;
4062 }
4063
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004064 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4065 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4066 hdev);
4067 goto unlock;
4068 }
4069
Johan Hedberg33e38b32013-03-15 17:07:05 -05004070 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4071 data, len);
4072 if (!cmd) {
4073 err = -ENOMEM;
4074 goto unlock;
4075 }
4076
4077 hci_req_init(&req, hdev);
4078
Johan Hedberg406d7802013-03-15 17:07:09 -05004079 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004080
4081 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004082 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004083 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004084 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004085 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004086 }
4087
Johan Hedberg33e38b32013-03-15 17:07:05 -05004088unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004089 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004090
Antti Julkuf6422ec2011-06-22 13:11:56 +03004091 return err;
4092}
4093
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004094static void set_bredr_scan(struct hci_request *req)
4095{
4096 struct hci_dev *hdev = req->hdev;
4097 u8 scan = 0;
4098
4099 /* Ensure that fast connectable is disabled. This function will
4100 * not do anything if the page scan parameters are already what
4101 * they should be.
4102 */
4103 write_fast_connectable(req, false);
4104
4105 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4106 scan |= SCAN_PAGE;
4107 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4108 scan |= SCAN_INQUIRY;
4109
4110 if (scan)
4111 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4112}
4113
Johan Hedberg0663ca22013-10-02 13:43:14 +03004114static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4115{
4116 struct pending_cmd *cmd;
4117
4118 BT_DBG("status 0x%02x", status);
4119
4120 hci_dev_lock(hdev);
4121
4122 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4123 if (!cmd)
4124 goto unlock;
4125
4126 if (status) {
4127 u8 mgmt_err = mgmt_status(status);
4128
4129 /* We need to restore the flag if related HCI commands
4130 * failed.
4131 */
4132 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4133
4134 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4135 } else {
4136 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4137 new_settings(hdev, cmd->sk);
4138 }
4139
4140 mgmt_pending_remove(cmd);
4141
4142unlock:
4143 hci_dev_unlock(hdev);
4144}
4145
4146static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4147{
4148 struct mgmt_mode *cp = data;
4149 struct pending_cmd *cmd;
4150 struct hci_request req;
4151 int err;
4152
4153 BT_DBG("request for %s", hdev->name);
4154
4155 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4156 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4157 MGMT_STATUS_NOT_SUPPORTED);
4158
4159 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4160 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4161 MGMT_STATUS_REJECTED);
4162
4163 if (cp->val != 0x00 && cp->val != 0x01)
4164 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4165 MGMT_STATUS_INVALID_PARAMS);
4166
4167 hci_dev_lock(hdev);
4168
4169 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4170 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4171 goto unlock;
4172 }
4173
4174 if (!hdev_is_powered(hdev)) {
4175 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004176 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4177 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4178 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4179 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4180 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4181 }
4182
4183 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4184
4185 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4186 if (err < 0)
4187 goto unlock;
4188
4189 err = new_settings(hdev, sk);
4190 goto unlock;
4191 }
4192
4193 /* Reject disabling when powered on */
4194 if (!cp->val) {
4195 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4196 MGMT_STATUS_REJECTED);
4197 goto unlock;
4198 }
4199
4200 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4201 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4202 MGMT_STATUS_BUSY);
4203 goto unlock;
4204 }
4205
4206 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4207 if (!cmd) {
4208 err = -ENOMEM;
4209 goto unlock;
4210 }
4211
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004212 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004213 * generates the correct flags.
4214 */
4215 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4216
4217 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004218
4219 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4220 set_bredr_scan(&req);
4221
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004222 /* Since only the advertising data flags will change, there
4223 * is no need to update the scan response data.
4224 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004225 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004226
Johan Hedberg0663ca22013-10-02 13:43:14 +03004227 err = hci_req_run(&req, set_bredr_complete);
4228 if (err < 0)
4229 mgmt_pending_remove(cmd);
4230
4231unlock:
4232 hci_dev_unlock(hdev);
4233 return err;
4234}
4235
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004236static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4237 void *data, u16 len)
4238{
4239 struct mgmt_mode *cp = data;
4240 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004241 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004242 int err;
4243
4244 BT_DBG("request for %s", hdev->name);
4245
4246 status = mgmt_bredr_support(hdev);
4247 if (status)
4248 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4249 status);
4250
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004251 if (!lmp_sc_capable(hdev) &&
4252 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004253 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4254 MGMT_STATUS_NOT_SUPPORTED);
4255
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004256 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004257 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4258 MGMT_STATUS_INVALID_PARAMS);
4259
4260 hci_dev_lock(hdev);
4261
4262 if (!hdev_is_powered(hdev)) {
4263 bool changed;
4264
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004265 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004266 changed = !test_and_set_bit(HCI_SC_ENABLED,
4267 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004268 if (cp->val == 0x02)
4269 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4270 else
4271 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4272 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004273 changed = test_and_clear_bit(HCI_SC_ENABLED,
4274 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004275 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4276 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004277
4278 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4279 if (err < 0)
4280 goto failed;
4281
4282 if (changed)
4283 err = new_settings(hdev, sk);
4284
4285 goto failed;
4286 }
4287
4288 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4289 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4290 MGMT_STATUS_BUSY);
4291 goto failed;
4292 }
4293
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004294 val = !!cp->val;
4295
4296 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4297 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004298 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4299 goto failed;
4300 }
4301
4302 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4303 if (!cmd) {
4304 err = -ENOMEM;
4305 goto failed;
4306 }
4307
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004308 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004309 if (err < 0) {
4310 mgmt_pending_remove(cmd);
4311 goto failed;
4312 }
4313
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004314 if (cp->val == 0x02)
4315 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4316 else
4317 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4318
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004319failed:
4320 hci_dev_unlock(hdev);
4321 return err;
4322}
4323
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004324static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4325 void *data, u16 len)
4326{
4327 struct mgmt_mode *cp = data;
4328 bool changed;
4329 int err;
4330
4331 BT_DBG("request for %s", hdev->name);
4332
4333 if (cp->val != 0x00 && cp->val != 0x01)
4334 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4335 MGMT_STATUS_INVALID_PARAMS);
4336
4337 hci_dev_lock(hdev);
4338
4339 if (cp->val)
4340 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4341 else
4342 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4343
4344 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4345 if (err < 0)
4346 goto unlock;
4347
4348 if (changed)
4349 err = new_settings(hdev, sk);
4350
4351unlock:
4352 hci_dev_unlock(hdev);
4353 return err;
4354}
4355
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004356static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4357 u16 len)
4358{
4359 struct mgmt_cp_set_privacy *cp = cp_data;
4360 bool changed;
4361 int err;
4362
4363 BT_DBG("request for %s", hdev->name);
4364
4365 if (!lmp_le_capable(hdev))
4366 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4367 MGMT_STATUS_NOT_SUPPORTED);
4368
4369 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4370 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4371 MGMT_STATUS_INVALID_PARAMS);
4372
4373 if (hdev_is_powered(hdev))
4374 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4375 MGMT_STATUS_REJECTED);
4376
4377 hci_dev_lock(hdev);
4378
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004379 /* If user space supports this command it is also expected to
4380 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4381 */
4382 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4383
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004384 if (cp->privacy) {
4385 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4386 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4387 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4388 } else {
4389 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4390 memset(hdev->irk, 0, sizeof(hdev->irk));
4391 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4392 }
4393
4394 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4395 if (err < 0)
4396 goto unlock;
4397
4398 if (changed)
4399 err = new_settings(hdev, sk);
4400
4401unlock:
4402 hci_dev_unlock(hdev);
4403 return err;
4404}
4405
Johan Hedberg41edf162014-02-18 10:19:35 +02004406static bool irk_is_valid(struct mgmt_irk_info *irk)
4407{
4408 switch (irk->addr.type) {
4409 case BDADDR_LE_PUBLIC:
4410 return true;
4411
4412 case BDADDR_LE_RANDOM:
4413 /* Two most significant bits shall be set */
4414 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4415 return false;
4416 return true;
4417 }
4418
4419 return false;
4420}
4421
4422static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4423 u16 len)
4424{
4425 struct mgmt_cp_load_irks *cp = cp_data;
4426 u16 irk_count, expected_len;
4427 int i, err;
4428
4429 BT_DBG("request for %s", hdev->name);
4430
4431 if (!lmp_le_capable(hdev))
4432 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4433 MGMT_STATUS_NOT_SUPPORTED);
4434
4435 irk_count = __le16_to_cpu(cp->irk_count);
4436
4437 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4438 if (expected_len != len) {
4439 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004440 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004441 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4442 MGMT_STATUS_INVALID_PARAMS);
4443 }
4444
4445 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4446
4447 for (i = 0; i < irk_count; i++) {
4448 struct mgmt_irk_info *key = &cp->irks[i];
4449
4450 if (!irk_is_valid(key))
4451 return cmd_status(sk, hdev->id,
4452 MGMT_OP_LOAD_IRKS,
4453 MGMT_STATUS_INVALID_PARAMS);
4454 }
4455
4456 hci_dev_lock(hdev);
4457
4458 hci_smp_irks_clear(hdev);
4459
4460 for (i = 0; i < irk_count; i++) {
4461 struct mgmt_irk_info *irk = &cp->irks[i];
4462 u8 addr_type;
4463
4464 if (irk->addr.type == BDADDR_LE_PUBLIC)
4465 addr_type = ADDR_LE_DEV_PUBLIC;
4466 else
4467 addr_type = ADDR_LE_DEV_RANDOM;
4468
4469 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4470 BDADDR_ANY);
4471 }
4472
4473 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4474
4475 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4476
4477 hci_dev_unlock(hdev);
4478
4479 return err;
4480}
4481
Johan Hedberg3f706b72013-01-20 14:27:16 +02004482static bool ltk_is_valid(struct mgmt_ltk_info *key)
4483{
4484 if (key->master != 0x00 && key->master != 0x01)
4485 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004486
4487 switch (key->addr.type) {
4488 case BDADDR_LE_PUBLIC:
4489 return true;
4490
4491 case BDADDR_LE_RANDOM:
4492 /* Two most significant bits shall be set */
4493 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4494 return false;
4495 return true;
4496 }
4497
4498 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004499}
4500
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004501static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004502 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004503{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004504 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4505 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004506 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004507
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004508 BT_DBG("request for %s", hdev->name);
4509
4510 if (!lmp_le_capable(hdev))
4511 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4512 MGMT_STATUS_NOT_SUPPORTED);
4513
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004514 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004515
4516 expected_len = sizeof(*cp) + key_count *
4517 sizeof(struct mgmt_ltk_info);
4518 if (expected_len != len) {
4519 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004520 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004521 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004522 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004523 }
4524
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004525 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004526
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004527 for (i = 0; i < key_count; i++) {
4528 struct mgmt_ltk_info *key = &cp->keys[i];
4529
Johan Hedberg3f706b72013-01-20 14:27:16 +02004530 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004531 return cmd_status(sk, hdev->id,
4532 MGMT_OP_LOAD_LONG_TERM_KEYS,
4533 MGMT_STATUS_INVALID_PARAMS);
4534 }
4535
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004536 hci_dev_lock(hdev);
4537
4538 hci_smp_ltks_clear(hdev);
4539
4540 for (i = 0; i < key_count; i++) {
4541 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004542 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004543
4544 if (key->addr.type == BDADDR_LE_PUBLIC)
4545 addr_type = ADDR_LE_DEV_PUBLIC;
4546 else
4547 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004548
4549 if (key->master)
4550 type = HCI_SMP_LTK;
4551 else
4552 type = HCI_SMP_LTK_SLAVE;
4553
Johan Hedberg61b43352014-05-29 19:36:53 +03004554 switch (key->type) {
4555 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004556 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004557 break;
4558 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004559 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004560 break;
4561 default:
4562 continue;
4563 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004564
Johan Hedberg35d70272014-02-19 14:57:47 +02004565 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004566 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004567 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004568 }
4569
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004570 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4571 NULL, 0);
4572
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004573 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004574
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004575 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004576}
4577
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004578struct cmd_conn_lookup {
4579 struct hci_conn *conn;
4580 bool valid_tx_power;
4581 u8 mgmt_status;
4582};
4583
4584static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4585{
4586 struct cmd_conn_lookup *match = data;
4587 struct mgmt_cp_get_conn_info *cp;
4588 struct mgmt_rp_get_conn_info rp;
4589 struct hci_conn *conn = cmd->user_data;
4590
4591 if (conn != match->conn)
4592 return;
4593
4594 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4595
4596 memset(&rp, 0, sizeof(rp));
4597 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4598 rp.addr.type = cp->addr.type;
4599
4600 if (!match->mgmt_status) {
4601 rp.rssi = conn->rssi;
4602
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004603 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004604 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004605 rp.max_tx_power = conn->max_tx_power;
4606 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004607 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004608 rp.max_tx_power = HCI_TX_POWER_INVALID;
4609 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004610 }
4611
4612 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4613 match->mgmt_status, &rp, sizeof(rp));
4614
4615 hci_conn_drop(conn);
4616
4617 mgmt_pending_remove(cmd);
4618}
4619
4620static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4621{
4622 struct hci_cp_read_rssi *cp;
4623 struct hci_conn *conn;
4624 struct cmd_conn_lookup match;
4625 u16 handle;
4626
4627 BT_DBG("status 0x%02x", status);
4628
4629 hci_dev_lock(hdev);
4630
4631 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004632 * otherwise we assume it's not valid. At the moment we assume that
4633 * either both or none of current and max values are valid to keep code
4634 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004635 */
4636 match.valid_tx_power = !status;
4637
4638 /* Commands sent in request are either Read RSSI or Read Transmit Power
4639 * Level so we check which one was last sent to retrieve connection
4640 * handle. Both commands have handle as first parameter so it's safe to
4641 * cast data on the same command struct.
4642 *
4643 * First command sent is always Read RSSI and we fail only if it fails.
4644 * In other case we simply override error to indicate success as we
4645 * already remembered if TX power value is actually valid.
4646 */
4647 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4648 if (!cp) {
4649 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4650 status = 0;
4651 }
4652
4653 if (!cp) {
4654 BT_ERR("invalid sent_cmd in response");
4655 goto unlock;
4656 }
4657
4658 handle = __le16_to_cpu(cp->handle);
4659 conn = hci_conn_hash_lookup_handle(hdev, handle);
4660 if (!conn) {
4661 BT_ERR("unknown handle (%d) in response", handle);
4662 goto unlock;
4663 }
4664
4665 match.conn = conn;
4666 match.mgmt_status = mgmt_status(status);
4667
4668 /* Cache refresh is complete, now reply for mgmt request for given
4669 * connection only.
4670 */
4671 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4672 get_conn_info_complete, &match);
4673
4674unlock:
4675 hci_dev_unlock(hdev);
4676}
4677
4678static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4679 u16 len)
4680{
4681 struct mgmt_cp_get_conn_info *cp = data;
4682 struct mgmt_rp_get_conn_info rp;
4683 struct hci_conn *conn;
4684 unsigned long conn_info_age;
4685 int err = 0;
4686
4687 BT_DBG("%s", hdev->name);
4688
4689 memset(&rp, 0, sizeof(rp));
4690 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4691 rp.addr.type = cp->addr.type;
4692
4693 if (!bdaddr_type_is_valid(cp->addr.type))
4694 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4695 MGMT_STATUS_INVALID_PARAMS,
4696 &rp, sizeof(rp));
4697
4698 hci_dev_lock(hdev);
4699
4700 if (!hdev_is_powered(hdev)) {
4701 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4702 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4703 goto unlock;
4704 }
4705
4706 if (cp->addr.type == BDADDR_BREDR)
4707 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4708 &cp->addr.bdaddr);
4709 else
4710 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4711
4712 if (!conn || conn->state != BT_CONNECTED) {
4713 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4714 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4715 goto unlock;
4716 }
4717
4718 /* To avoid client trying to guess when to poll again for information we
4719 * calculate conn info age as random value between min/max set in hdev.
4720 */
4721 conn_info_age = hdev->conn_info_min_age +
4722 prandom_u32_max(hdev->conn_info_max_age -
4723 hdev->conn_info_min_age);
4724
4725 /* Query controller to refresh cached values if they are too old or were
4726 * never read.
4727 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004728 if (time_after(jiffies, conn->conn_info_timestamp +
4729 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004730 !conn->conn_info_timestamp) {
4731 struct hci_request req;
4732 struct hci_cp_read_tx_power req_txp_cp;
4733 struct hci_cp_read_rssi req_rssi_cp;
4734 struct pending_cmd *cmd;
4735
4736 hci_req_init(&req, hdev);
4737 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4738 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4739 &req_rssi_cp);
4740
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004741 /* For LE links TX power does not change thus we don't need to
4742 * query for it once value is known.
4743 */
4744 if (!bdaddr_type_is_le(cp->addr.type) ||
4745 conn->tx_power == HCI_TX_POWER_INVALID) {
4746 req_txp_cp.handle = cpu_to_le16(conn->handle);
4747 req_txp_cp.type = 0x00;
4748 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4749 sizeof(req_txp_cp), &req_txp_cp);
4750 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004751
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004752 /* Max TX power needs to be read only once per connection */
4753 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4754 req_txp_cp.handle = cpu_to_le16(conn->handle);
4755 req_txp_cp.type = 0x01;
4756 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4757 sizeof(req_txp_cp), &req_txp_cp);
4758 }
4759
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004760 err = hci_req_run(&req, conn_info_refresh_complete);
4761 if (err < 0)
4762 goto unlock;
4763
4764 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4765 data, len);
4766 if (!cmd) {
4767 err = -ENOMEM;
4768 goto unlock;
4769 }
4770
4771 hci_conn_hold(conn);
4772 cmd->user_data = conn;
4773
4774 conn->conn_info_timestamp = jiffies;
4775 } else {
4776 /* Cache is valid, just reply with values cached in hci_conn */
4777 rp.rssi = conn->rssi;
4778 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004779 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004780
4781 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4782 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4783 }
4784
4785unlock:
4786 hci_dev_unlock(hdev);
4787 return err;
4788}
4789
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004790static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004791 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4792 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004793 bool var_len;
4794 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004795} mgmt_handlers[] = {
4796 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004797 { read_version, false, MGMT_READ_VERSION_SIZE },
4798 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4799 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4800 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4801 { set_powered, false, MGMT_SETTING_SIZE },
4802 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4803 { set_connectable, false, MGMT_SETTING_SIZE },
4804 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4805 { set_pairable, false, MGMT_SETTING_SIZE },
4806 { set_link_security, false, MGMT_SETTING_SIZE },
4807 { set_ssp, false, MGMT_SETTING_SIZE },
4808 { set_hs, false, MGMT_SETTING_SIZE },
4809 { set_le, false, MGMT_SETTING_SIZE },
4810 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4811 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4812 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4813 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4814 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4815 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4816 { disconnect, false, MGMT_DISCONNECT_SIZE },
4817 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4818 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4819 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4820 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4821 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4822 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4823 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4824 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4825 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4826 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4827 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4828 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004829 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004830 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4831 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4832 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4833 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4834 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4835 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004836 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004837 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004838 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004839 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004840 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004841 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004842 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004843 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004844 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004845 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004846};
4847
4848
Johan Hedberg03811012010-12-08 00:21:06 +02004849int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4850{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004851 void *buf;
4852 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004853 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004854 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004855 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004856 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004857 int err;
4858
4859 BT_DBG("got %zu bytes", msglen);
4860
4861 if (msglen < sizeof(*hdr))
4862 return -EINVAL;
4863
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004864 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004865 if (!buf)
4866 return -ENOMEM;
4867
4868 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4869 err = -EFAULT;
4870 goto done;
4871 }
4872
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004873 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004874 opcode = __le16_to_cpu(hdr->opcode);
4875 index = __le16_to_cpu(hdr->index);
4876 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004877
4878 if (len != msglen - sizeof(*hdr)) {
4879 err = -EINVAL;
4880 goto done;
4881 }
4882
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004883 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004884 hdev = hci_dev_get(index);
4885 if (!hdev) {
4886 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004887 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004888 goto done;
4889 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004890
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004891 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4892 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004893 err = cmd_status(sk, index, opcode,
4894 MGMT_STATUS_INVALID_INDEX);
4895 goto done;
4896 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004897 }
4898
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004899 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004900 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004901 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004902 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004903 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004904 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004905 }
4906
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004907 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004908 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004909 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004910 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004911 goto done;
4912 }
4913
Johan Hedbergbe22b542012-03-01 22:24:41 +02004914 handler = &mgmt_handlers[opcode];
4915
4916 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004917 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004918 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004919 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004920 goto done;
4921 }
4922
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004923 if (hdev)
4924 mgmt_init_hdev(sk, hdev);
4925
4926 cp = buf + sizeof(*hdr);
4927
Johan Hedbergbe22b542012-03-01 22:24:41 +02004928 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004929 if (err < 0)
4930 goto done;
4931
Johan Hedberg03811012010-12-08 00:21:06 +02004932 err = msglen;
4933
4934done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004935 if (hdev)
4936 hci_dev_put(hdev);
4937
Johan Hedberg03811012010-12-08 00:21:06 +02004938 kfree(buf);
4939 return err;
4940}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004941
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004942void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004943{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004944 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004945 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004946
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004947 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004948}
4949
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004950void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004951{
Johan Hedberg5f159032012-03-02 03:13:19 +02004952 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004953
Marcel Holtmann1514b892013-10-06 08:25:01 -07004954 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004955 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004956
Johan Hedberg744cf192011-11-08 20:40:14 +02004957 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004958
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004959 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004960}
4961
Andre Guedes6046dc32014-02-26 20:21:51 -03004962/* This function requires the caller holds hdev->lock */
4963static void restart_le_auto_conns(struct hci_dev *hdev)
4964{
4965 struct hci_conn_params *p;
4966
4967 list_for_each_entry(p, &hdev->le_conn_params, list) {
4968 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4969 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4970 }
4971}
4972
Johan Hedberg229ab392013-03-15 17:06:53 -05004973static void powered_complete(struct hci_dev *hdev, u8 status)
4974{
4975 struct cmd_lookup match = { NULL, hdev };
4976
4977 BT_DBG("status 0x%02x", status);
4978
4979 hci_dev_lock(hdev);
4980
Andre Guedes6046dc32014-02-26 20:21:51 -03004981 restart_le_auto_conns(hdev);
4982
Johan Hedberg229ab392013-03-15 17:06:53 -05004983 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4984
4985 new_settings(hdev, match.sk);
4986
4987 hci_dev_unlock(hdev);
4988
4989 if (match.sk)
4990 sock_put(match.sk);
4991}
4992
Johan Hedberg70da6242013-03-15 17:06:51 -05004993static int powered_update_hci(struct hci_dev *hdev)
4994{
Johan Hedberg890ea892013-03-15 17:06:52 -05004995 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004996 u8 link_sec;
4997
Johan Hedberg890ea892013-03-15 17:06:52 -05004998 hci_req_init(&req, hdev);
4999
Johan Hedberg70da6242013-03-15 17:06:51 -05005000 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5001 !lmp_host_ssp_capable(hdev)) {
5002 u8 ssp = 1;
5003
Johan Hedberg890ea892013-03-15 17:06:52 -05005004 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005005 }
5006
Johan Hedbergc73eee92013-04-19 18:35:21 +03005007 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5008 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005009 struct hci_cp_write_le_host_supported cp;
5010
5011 cp.le = 1;
5012 cp.simul = lmp_le_br_capable(hdev);
5013
5014 /* Check first if we already have the right
5015 * host state (host features set)
5016 */
5017 if (cp.le != lmp_host_le_capable(hdev) ||
5018 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005019 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5020 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005021 }
5022
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005023 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005024 /* Make sure the controller has a good default for
5025 * advertising data. This also applies to the case
5026 * where BR/EDR was toggled during the AUTO_OFF phase.
5027 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005028 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005029 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005030 update_scan_rsp_data(&req);
5031 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005032
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005033 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5034 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005035 }
5036
Johan Hedberg70da6242013-03-15 17:06:51 -05005037 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5038 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005039 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5040 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005041
5042 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005043 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5044 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005045 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005046 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005047 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005048 }
5049
Johan Hedberg229ab392013-03-15 17:06:53 -05005050 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005051}
5052
Johan Hedberg744cf192011-11-08 20:40:14 +02005053int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005054{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005055 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005056 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5057 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005058 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005059
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005060 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5061 return 0;
5062
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005063 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005064 if (powered_update_hci(hdev) == 0)
5065 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005066
Johan Hedberg229ab392013-03-15 17:06:53 -05005067 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5068 &match);
5069 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005070 }
5071
Johan Hedberg229ab392013-03-15 17:06:53 -05005072 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5073 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5074
5075 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5076 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5077 zero_cod, sizeof(zero_cod), NULL);
5078
5079new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005080 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005081
5082 if (match.sk)
5083 sock_put(match.sk);
5084
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005085 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005086}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005087
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005088void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005089{
5090 struct pending_cmd *cmd;
5091 u8 status;
5092
5093 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5094 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005095 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005096
5097 if (err == -ERFKILL)
5098 status = MGMT_STATUS_RFKILLED;
5099 else
5100 status = MGMT_STATUS_FAILED;
5101
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005102 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005103
5104 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005105}
5106
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005107void mgmt_discoverable_timeout(struct hci_dev *hdev)
5108{
5109 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005110
5111 hci_dev_lock(hdev);
5112
5113 /* When discoverable timeout triggers, then just make sure
5114 * the limited discoverable flag is cleared. Even in the case
5115 * of a timeout triggered from general discoverable, it is
5116 * safe to unconditionally clear the flag.
5117 */
5118 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005119 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005120
5121 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005122 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5123 u8 scan = SCAN_PAGE;
5124 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5125 sizeof(scan), &scan);
5126 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005127 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005128 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005129 hci_req_run(&req, NULL);
5130
5131 hdev->discov_timeout = 0;
5132
Johan Hedberg9a43e252013-10-20 19:00:07 +03005133 new_settings(hdev, NULL);
5134
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005135 hci_dev_unlock(hdev);
5136}
5137
Marcel Holtmann86a75642013-10-15 06:33:54 -07005138void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005139{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005140 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005141
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005142 /* Nothing needed here if there's a pending command since that
5143 * commands request completion callback takes care of everything
5144 * necessary.
5145 */
5146 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005147 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005148
Johan Hedbergbd107992014-02-24 14:52:19 +02005149 /* Powering off may clear the scan mode - don't let that interfere */
5150 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5151 return;
5152
Johan Hedberg9a43e252013-10-20 19:00:07 +03005153 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005154 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005155 } else {
5156 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005157 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005158 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005159
Johan Hedberg9a43e252013-10-20 19:00:07 +03005160 if (changed) {
5161 struct hci_request req;
5162
5163 /* In case this change in discoverable was triggered by
5164 * a disabling of connectable there could be a need to
5165 * update the advertising flags.
5166 */
5167 hci_req_init(&req, hdev);
5168 update_adv_data(&req);
5169 hci_req_run(&req, NULL);
5170
Marcel Holtmann86a75642013-10-15 06:33:54 -07005171 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005172 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005173}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005174
Marcel Holtmanna3309162013-10-15 06:33:55 -07005175void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005176{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005177 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005178
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005179 /* Nothing needed here if there's a pending command since that
5180 * commands request completion callback takes care of everything
5181 * necessary.
5182 */
5183 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005184 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005185
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005186 /* Powering off may clear the scan mode - don't let that interfere */
5187 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5188 return;
5189
Marcel Holtmanna3309162013-10-15 06:33:55 -07005190 if (connectable)
5191 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5192 else
5193 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005194
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005195 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005196 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005197}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005198
Johan Hedberg778b2352014-02-24 14:52:17 +02005199void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5200{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005201 /* Powering off may stop advertising - don't let that interfere */
5202 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5203 return;
5204
Johan Hedberg778b2352014-02-24 14:52:17 +02005205 if (advertising)
5206 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5207 else
5208 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5209}
5210
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005211void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005212{
Johan Hedbergca69b792011-11-11 18:10:00 +02005213 u8 mgmt_err = mgmt_status(status);
5214
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005215 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005216 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005217 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005218
5219 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005220 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005221 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005222}
5223
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005224void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5225 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005226{
Johan Hedberg86742e12011-11-07 23:13:38 +02005227 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005228
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005229 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005230
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005231 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005232 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005233 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005234 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005235 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005236 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005237
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005238 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005239}
Johan Hedbergf7520542011-01-20 12:34:39 +02005240
Johan Hedbergd7b25452014-05-23 13:19:53 +03005241static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5242{
5243 if (ltk->authenticated)
5244 return MGMT_LTK_AUTHENTICATED;
5245
5246 return MGMT_LTK_UNAUTHENTICATED;
5247}
5248
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005249void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005250{
5251 struct mgmt_ev_new_long_term_key ev;
5252
5253 memset(&ev, 0, sizeof(ev));
5254
Marcel Holtmann5192d302014-02-19 17:11:58 -08005255 /* Devices using resolvable or non-resolvable random addresses
5256 * without providing an indentity resolving key don't require
5257 * to store long term keys. Their addresses will change the
5258 * next time around.
5259 *
5260 * Only when a remote device provides an identity address
5261 * make sure the long term key is stored. If the remote
5262 * identity is known, the long term keys are internally
5263 * mapped to the identity address. So allow static random
5264 * and public addresses here.
5265 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005266 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5267 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5268 ev.store_hint = 0x00;
5269 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005270 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005271
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005272 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005273 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005274 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005275 ev.key.enc_size = key->enc_size;
5276 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005277 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005278
5279 if (key->type == HCI_SMP_LTK)
5280 ev.key.master = 1;
5281
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005282 memcpy(ev.key.val, key->val, sizeof(key->val));
5283
Marcel Holtmann083368f2013-10-15 14:26:29 -07005284 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005285}
5286
Johan Hedberg95fbac82014-02-19 15:18:31 +02005287void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5288{
5289 struct mgmt_ev_new_irk ev;
5290
5291 memset(&ev, 0, sizeof(ev));
5292
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005293 /* For identity resolving keys from devices that are already
5294 * using a public address or static random address, do not
5295 * ask for storing this key. The identity resolving key really
5296 * is only mandatory for devices using resovlable random
5297 * addresses.
5298 *
5299 * Storing all identity resolving keys has the downside that
5300 * they will be also loaded on next boot of they system. More
5301 * identity resolving keys, means more time during scanning is
5302 * needed to actually resolve these addresses.
5303 */
5304 if (bacmp(&irk->rpa, BDADDR_ANY))
5305 ev.store_hint = 0x01;
5306 else
5307 ev.store_hint = 0x00;
5308
Johan Hedberg95fbac82014-02-19 15:18:31 +02005309 bacpy(&ev.rpa, &irk->rpa);
5310 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5311 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5312 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5313
5314 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5315}
5316
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005317void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5318 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005319{
5320 struct mgmt_ev_new_csrk ev;
5321
5322 memset(&ev, 0, sizeof(ev));
5323
5324 /* Devices using resolvable or non-resolvable random addresses
5325 * without providing an indentity resolving key don't require
5326 * to store signature resolving keys. Their addresses will change
5327 * the next time around.
5328 *
5329 * Only when a remote device provides an identity address
5330 * make sure the signature resolving key is stored. So allow
5331 * static random and public addresses here.
5332 */
5333 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5334 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5335 ev.store_hint = 0x00;
5336 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005337 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005338
5339 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5340 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5341 ev.key.master = csrk->master;
5342 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5343
5344 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5345}
5346
Marcel Holtmann94933992013-10-15 10:26:39 -07005347static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5348 u8 data_len)
5349{
5350 eir[eir_len++] = sizeof(type) + data_len;
5351 eir[eir_len++] = type;
5352 memcpy(&eir[eir_len], data, data_len);
5353 eir_len += data_len;
5354
5355 return eir_len;
5356}
5357
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005358void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5359 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5360 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005361{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005362 char buf[512];
5363 struct mgmt_ev_device_connected *ev = (void *) buf;
5364 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005365
Johan Hedbergb644ba32012-01-17 21:48:47 +02005366 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005367 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005368
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005369 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005370
Johan Hedbergb644ba32012-01-17 21:48:47 +02005371 if (name_len > 0)
5372 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005373 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005374
5375 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005376 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005377 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005378
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005379 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005380
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005381 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5382 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005383}
5384
Johan Hedberg8962ee72011-01-20 12:40:27 +02005385static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5386{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005387 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005388 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005389 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005390
Johan Hedberg88c3df12012-02-09 14:27:38 +02005391 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5392 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005393
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005394 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005395 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005396
5397 *sk = cmd->sk;
5398 sock_hold(*sk);
5399
Johan Hedberga664b5b2011-02-19 12:06:02 -03005400 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005401}
5402
Johan Hedberg124f6e32012-02-09 13:50:12 +02005403static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005404{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005405 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005406 struct mgmt_cp_unpair_device *cp = cmd->param;
5407 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005408
5409 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005410 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5411 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005412
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005413 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5414
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005415 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005416
5417 mgmt_pending_remove(cmd);
5418}
5419
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005420void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005421 u8 link_type, u8 addr_type, u8 reason,
5422 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005423{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005424 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005425 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005426 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005427
Johan Hedberg8b064a32014-02-24 14:52:22 +02005428 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5429 if (power_off) {
5430 struct mgmt_mode *cp = power_off->param;
5431
5432 /* The connection is still in hci_conn_hash so test for 1
5433 * instead of 0 to know if this is the last one.
5434 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005435 if (!cp->val && hci_conn_count(hdev) == 1) {
5436 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005437 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005438 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005439 }
5440
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005441 if (!mgmt_connected)
5442 return;
5443
Andre Guedes57eb7762013-10-30 19:01:41 -03005444 if (link_type != ACL_LINK && link_type != LE_LINK)
5445 return;
5446
Johan Hedberg744cf192011-11-08 20:40:14 +02005447 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005448
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005449 bacpy(&ev.addr.bdaddr, bdaddr);
5450 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5451 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005452
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005453 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005454
5455 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005456 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005457
Johan Hedberg124f6e32012-02-09 13:50:12 +02005458 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005459 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005460}
5461
Marcel Holtmann78929242013-10-06 23:55:47 -07005462void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5463 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005464{
Andre Guedes3655bba2013-10-30 19:01:40 -03005465 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5466 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005467 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005468 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005469
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005470 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5471 hdev);
5472
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005473 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005474 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005475 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005476
Andre Guedes3655bba2013-10-30 19:01:40 -03005477 cp = cmd->param;
5478
5479 if (bacmp(bdaddr, &cp->addr.bdaddr))
5480 return;
5481
5482 if (cp->addr.type != bdaddr_type)
5483 return;
5484
Johan Hedberg88c3df12012-02-09 14:27:38 +02005485 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005486 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005487
Marcel Holtmann78929242013-10-06 23:55:47 -07005488 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5489 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005490
Johan Hedberga664b5b2011-02-19 12:06:02 -03005491 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005492}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005493
Marcel Holtmann445608d2013-10-06 23:55:48 -07005494void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5495 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005496{
5497 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005498 struct pending_cmd *power_off;
5499
5500 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5501 if (power_off) {
5502 struct mgmt_mode *cp = power_off->param;
5503
5504 /* The connection is still in hci_conn_hash so test for 1
5505 * instead of 0 to know if this is the last one.
5506 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005507 if (!cp->val && hci_conn_count(hdev) == 1) {
5508 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005509 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005510 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005511 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005512
Johan Hedberg4c659c32011-11-07 23:13:39 +02005513 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005514 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005515 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005516
Marcel Holtmann445608d2013-10-06 23:55:48 -07005517 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005518}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005519
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005520void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005521{
5522 struct mgmt_ev_pin_code_request ev;
5523
Johan Hedbergd8457692012-02-17 14:24:57 +02005524 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005525 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005526 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005527
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005528 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005529}
5530
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005531void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5532 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005533{
5534 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005535 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005536
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005537 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005538 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005539 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005540
Johan Hedbergd8457692012-02-17 14:24:57 +02005541 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005542 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005543
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005544 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5545 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005546
Johan Hedberga664b5b2011-02-19 12:06:02 -03005547 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005548}
5549
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005550void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5551 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005552{
5553 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005554 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005555
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005556 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005557 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005558 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005559
Johan Hedbergd8457692012-02-17 14:24:57 +02005560 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005561 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005562
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005563 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5564 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005565
Johan Hedberga664b5b2011-02-19 12:06:02 -03005566 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005567}
Johan Hedberga5c29682011-02-19 12:05:57 -03005568
Johan Hedberg744cf192011-11-08 20:40:14 +02005569int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005570 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005571 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005572{
5573 struct mgmt_ev_user_confirm_request ev;
5574
Johan Hedberg744cf192011-11-08 20:40:14 +02005575 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005576
Johan Hedberg272d90d2012-02-09 15:26:12 +02005577 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005578 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005579 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005580 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005581
Johan Hedberg744cf192011-11-08 20:40:14 +02005582 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005583 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005584}
5585
Johan Hedberg272d90d2012-02-09 15:26:12 +02005586int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005587 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005588{
5589 struct mgmt_ev_user_passkey_request ev;
5590
5591 BT_DBG("%s", hdev->name);
5592
Johan Hedberg272d90d2012-02-09 15:26:12 +02005593 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005594 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005595
5596 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005597 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005598}
5599
Brian Gix0df4c182011-11-16 13:53:13 -08005600static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005601 u8 link_type, u8 addr_type, u8 status,
5602 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005603{
5604 struct pending_cmd *cmd;
5605 struct mgmt_rp_user_confirm_reply rp;
5606 int err;
5607
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005608 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005609 if (!cmd)
5610 return -ENOENT;
5611
Johan Hedberg272d90d2012-02-09 15:26:12 +02005612 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005613 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005614 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005615 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005616
Johan Hedberga664b5b2011-02-19 12:06:02 -03005617 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005618
5619 return err;
5620}
5621
Johan Hedberg744cf192011-11-08 20:40:14 +02005622int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005623 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005624{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005625 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005626 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005627}
5628
Johan Hedberg272d90d2012-02-09 15:26:12 +02005629int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005630 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005631{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005632 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005633 status,
5634 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005635}
Johan Hedberg2a611692011-02-19 12:06:00 -03005636
Brian Gix604086b2011-11-23 08:28:33 -08005637int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005638 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005639{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005640 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005641 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005642}
5643
Johan Hedberg272d90d2012-02-09 15:26:12 +02005644int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005645 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005646{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005647 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005648 status,
5649 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005650}
5651
Johan Hedberg92a25252012-09-06 18:39:26 +03005652int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5653 u8 link_type, u8 addr_type, u32 passkey,
5654 u8 entered)
5655{
5656 struct mgmt_ev_passkey_notify ev;
5657
5658 BT_DBG("%s", hdev->name);
5659
5660 bacpy(&ev.addr.bdaddr, bdaddr);
5661 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5662 ev.passkey = __cpu_to_le32(passkey);
5663 ev.entered = entered;
5664
5665 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5666}
5667
Marcel Holtmanne5460992013-10-15 14:26:23 -07005668void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5669 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005670{
5671 struct mgmt_ev_auth_failed ev;
5672
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005673 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005674 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005675 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005676
Marcel Holtmanne5460992013-10-15 14:26:23 -07005677 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005678}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005679
Marcel Holtmann464996a2013-10-15 14:26:24 -07005680void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005681{
5682 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005683 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005684
5685 if (status) {
5686 u8 mgmt_err = mgmt_status(status);
5687 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005688 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005689 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005690 }
5691
Marcel Holtmann464996a2013-10-15 14:26:24 -07005692 if (test_bit(HCI_AUTH, &hdev->flags))
5693 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5694 &hdev->dev_flags);
5695 else
5696 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5697 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005698
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005699 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005700 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005701
Johan Hedberg47990ea2012-02-22 11:58:37 +02005702 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005703 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005704
5705 if (match.sk)
5706 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005707}
5708
Johan Hedberg890ea892013-03-15 17:06:52 -05005709static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005710{
Johan Hedberg890ea892013-03-15 17:06:52 -05005711 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005712 struct hci_cp_write_eir cp;
5713
Johan Hedberg976eb202012-10-24 21:12:01 +03005714 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005715 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005716
Johan Hedbergc80da272012-02-22 15:38:48 +02005717 memset(hdev->eir, 0, sizeof(hdev->eir));
5718
Johan Hedbergcacaf522012-02-21 00:52:42 +02005719 memset(&cp, 0, sizeof(cp));
5720
Johan Hedberg890ea892013-03-15 17:06:52 -05005721 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005722}
5723
Marcel Holtmann3e248562013-10-15 14:26:25 -07005724void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005725{
5726 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005727 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005728 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005729
5730 if (status) {
5731 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005732
5733 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005734 &hdev->dev_flags)) {
5735 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005736 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005737 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005738
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005739 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5740 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005741 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005742 }
5743
5744 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005745 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005746 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005747 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5748 if (!changed)
5749 changed = test_and_clear_bit(HCI_HS_ENABLED,
5750 &hdev->dev_flags);
5751 else
5752 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005753 }
5754
5755 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5756
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005757 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005758 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005759
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005760 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005761 sock_put(match.sk);
5762
Johan Hedberg890ea892013-03-15 17:06:52 -05005763 hci_req_init(&req, hdev);
5764
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005765 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005766 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005767 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005768 clear_eir(&req);
5769
5770 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005771}
5772
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005773void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5774{
5775 struct cmd_lookup match = { NULL, hdev };
5776 bool changed = false;
5777
5778 if (status) {
5779 u8 mgmt_err = mgmt_status(status);
5780
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005781 if (enable) {
5782 if (test_and_clear_bit(HCI_SC_ENABLED,
5783 &hdev->dev_flags))
5784 new_settings(hdev, NULL);
5785 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5786 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005787
5788 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5789 cmd_status_rsp, &mgmt_err);
5790 return;
5791 }
5792
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005793 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005794 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005795 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005796 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005797 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5798 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005799
5800 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5801 settings_rsp, &match);
5802
5803 if (changed)
5804 new_settings(hdev, match.sk);
5805
5806 if (match.sk)
5807 sock_put(match.sk);
5808}
5809
Johan Hedberg92da6092013-03-15 17:06:55 -05005810static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005811{
5812 struct cmd_lookup *match = data;
5813
Johan Hedberg90e70452012-02-23 23:09:40 +02005814 if (match->sk == NULL) {
5815 match->sk = cmd->sk;
5816 sock_hold(match->sk);
5817 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005818}
5819
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005820void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5821 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005822{
Johan Hedberg90e70452012-02-23 23:09:40 +02005823 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005824
Johan Hedberg92da6092013-03-15 17:06:55 -05005825 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5826 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5827 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005828
5829 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005830 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5831 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005832
5833 if (match.sk)
5834 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005835}
5836
Marcel Holtmann7667da32013-10-15 14:26:27 -07005837void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005838{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005839 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005840 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005841
Johan Hedberg13928972013-03-15 17:07:00 -05005842 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005843 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005844
5845 memset(&ev, 0, sizeof(ev));
5846 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005847 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005848
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005849 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005850 if (!cmd) {
5851 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005852
Johan Hedberg13928972013-03-15 17:07:00 -05005853 /* If this is a HCI command related to powering on the
5854 * HCI dev don't send any mgmt signals.
5855 */
5856 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005857 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005858 }
5859
Marcel Holtmann7667da32013-10-15 14:26:27 -07005860 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5861 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005862}
Szymon Jancc35938b2011-03-22 13:12:21 +01005863
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005864void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5865 u8 *randomizer192, u8 *hash256,
5866 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005867{
5868 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005869
Johan Hedberg744cf192011-11-08 20:40:14 +02005870 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005871
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005872 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005873 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005874 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005875
5876 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005877 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5878 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005879 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005880 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5881 hash256 && randomizer256) {
5882 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005883
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005884 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5885 memcpy(rp.randomizer192, randomizer192,
5886 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005887
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005888 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5889 memcpy(rp.randomizer256, randomizer256,
5890 sizeof(rp.randomizer256));
5891
5892 cmd_complete(cmd->sk, hdev->id,
5893 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5894 &rp, sizeof(rp));
5895 } else {
5896 struct mgmt_rp_read_local_oob_data rp;
5897
5898 memcpy(rp.hash, hash192, sizeof(rp.hash));
5899 memcpy(rp.randomizer, randomizer192,
5900 sizeof(rp.randomizer));
5901
5902 cmd_complete(cmd->sk, hdev->id,
5903 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5904 &rp, sizeof(rp));
5905 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005906 }
5907
5908 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005909}
Johan Hedberge17acd42011-03-30 23:57:16 +03005910
Marcel Holtmann901801b2013-10-06 23:55:51 -07005911void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005912 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5913 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005914 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005915{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005916 char buf[512];
5917 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005918 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005919 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005920
Andre Guedes12602d02013-04-30 15:29:40 -03005921 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005922 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005923
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005924 /* Make sure that the buffer is big enough. The 5 extra bytes
5925 * are for the potential CoD field.
5926 */
5927 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005928 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005929
Johan Hedberg1dc06092012-01-15 21:01:23 +02005930 memset(buf, 0, sizeof(buf));
5931
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005932 irk = hci_get_irk(hdev, bdaddr, addr_type);
5933 if (irk) {
5934 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5935 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5936 } else {
5937 bacpy(&ev->addr.bdaddr, bdaddr);
5938 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5939 }
5940
Johan Hedberge319d2e2012-01-15 19:51:59 +02005941 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005942 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005943 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005944 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005945 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005946
Johan Hedberg1dc06092012-01-15 21:01:23 +02005947 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005948 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005949
Johan Hedberg1dc06092012-01-15 21:01:23 +02005950 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5951 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005952 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005953
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005954 if (scan_rsp_len > 0)
5955 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5956
5957 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5958 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005959
Marcel Holtmann901801b2013-10-06 23:55:51 -07005960 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005961}
Johan Hedberga88a9652011-03-30 13:18:12 +03005962
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005963void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5964 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005965{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005966 struct mgmt_ev_device_found *ev;
5967 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5968 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005969
Johan Hedbergb644ba32012-01-17 21:48:47 +02005970 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005971
Johan Hedbergb644ba32012-01-17 21:48:47 +02005972 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005973
Johan Hedbergb644ba32012-01-17 21:48:47 +02005974 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005975 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005976 ev->rssi = rssi;
5977
5978 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005979 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005980
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005981 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005982
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005983 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005984}
Johan Hedberg314b2382011-04-27 10:29:57 -04005985
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005986void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005987{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005988 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005989 struct pending_cmd *cmd;
5990
Andre Guedes343fb142011-11-22 17:14:19 -03005991 BT_DBG("%s discovering %u", hdev->name, discovering);
5992
Johan Hedberg164a6e72011-11-01 17:06:44 +02005993 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005994 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005995 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005996 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005997
5998 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005999 u8 type = hdev->discovery.type;
6000
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006001 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6002 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006003 mgmt_pending_remove(cmd);
6004 }
6005
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006006 memset(&ev, 0, sizeof(ev));
6007 ev.type = hdev->discovery.type;
6008 ev.discovering = discovering;
6009
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006010 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006011}
Antti Julku5e762442011-08-25 16:48:02 +03006012
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006013int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006014{
6015 struct pending_cmd *cmd;
6016 struct mgmt_ev_device_blocked ev;
6017
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006018 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006019
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006020 bacpy(&ev.addr.bdaddr, bdaddr);
6021 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006022
Johan Hedberg744cf192011-11-08 20:40:14 +02006023 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006024 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006025}
6026
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006027int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006028{
6029 struct pending_cmd *cmd;
6030 struct mgmt_ev_device_unblocked ev;
6031
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006032 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006033
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006034 bacpy(&ev.addr.bdaddr, bdaddr);
6035 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006036
Johan Hedberg744cf192011-11-08 20:40:14 +02006037 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006038 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006039}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006040
6041static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6042{
6043 BT_DBG("%s status %u", hdev->name, status);
6044
6045 /* Clear the advertising mgmt setting if we failed to re-enable it */
6046 if (status) {
6047 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006048 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006049 }
6050}
6051
6052void mgmt_reenable_advertising(struct hci_dev *hdev)
6053{
6054 struct hci_request req;
6055
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006056 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006057 return;
6058
6059 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6060 return;
6061
6062 hci_req_init(&req, hdev);
6063 enable_advertising(&req);
6064
6065 /* If this fails we have no option but to let user space know
6066 * that we've disabled advertising.
6067 */
6068 if (hci_req_run(&req, adv_enable_complete) < 0) {
6069 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006070 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006071 }
6072}