blob: 50a0a3ec50b07bd0f51475b6de76270f5ebf7fca [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 Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
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 Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020092};
93
94static const u16 mgmt_events[] = {
95 MGMT_EV_CONTROLLER_ERROR,
96 MGMT_EV_INDEX_ADDED,
97 MGMT_EV_INDEX_REMOVED,
98 MGMT_EV_NEW_SETTINGS,
99 MGMT_EV_CLASS_OF_DEV_CHANGED,
100 MGMT_EV_LOCAL_NAME_CHANGED,
101 MGMT_EV_NEW_LINK_KEY,
102 MGMT_EV_NEW_LONG_TERM_KEY,
103 MGMT_EV_DEVICE_CONNECTED,
104 MGMT_EV_DEVICE_DISCONNECTED,
105 MGMT_EV_CONNECT_FAILED,
106 MGMT_EV_PIN_CODE_REQUEST,
107 MGMT_EV_USER_CONFIRM_REQUEST,
108 MGMT_EV_USER_PASSKEY_REQUEST,
109 MGMT_EV_AUTH_FAILED,
110 MGMT_EV_DEVICE_FOUND,
111 MGMT_EV_DISCOVERING,
112 MGMT_EV_DEVICE_BLOCKED,
113 MGMT_EV_DEVICE_UNBLOCKED,
114 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300115 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800116 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700117 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200118 MGMT_EV_DEVICE_ADDED,
119 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300120 MGMT_EV_NEW_CONN_PARAM,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200121};
122
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800123#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200124
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200125#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
126 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
127
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200128struct pending_cmd {
129 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200130 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200131 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100132 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300134 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200135};
136
Johan Hedbergca69b792011-11-11 18:10:00 +0200137/* HCI to MGMT error code conversion table */
138static u8 mgmt_status_table[] = {
139 MGMT_STATUS_SUCCESS,
140 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
141 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
142 MGMT_STATUS_FAILED, /* Hardware Failure */
143 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
144 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200145 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200146 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
147 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
148 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
149 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
150 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
151 MGMT_STATUS_BUSY, /* Command Disallowed */
152 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
153 MGMT_STATUS_REJECTED, /* Rejected Security */
154 MGMT_STATUS_REJECTED, /* Rejected Personal */
155 MGMT_STATUS_TIMEOUT, /* Host Timeout */
156 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
157 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
158 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
159 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
160 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
161 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
162 MGMT_STATUS_BUSY, /* Repeated Attempts */
163 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
164 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
165 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
166 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
167 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
168 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
169 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
170 MGMT_STATUS_FAILED, /* Unspecified Error */
171 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
172 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
173 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
174 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
175 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
176 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
177 MGMT_STATUS_FAILED, /* Unit Link Key Used */
178 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
179 MGMT_STATUS_TIMEOUT, /* Instant Passed */
180 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
181 MGMT_STATUS_FAILED, /* Transaction Collision */
182 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
183 MGMT_STATUS_REJECTED, /* QoS Rejected */
184 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
185 MGMT_STATUS_REJECTED, /* Insufficient Security */
186 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
187 MGMT_STATUS_BUSY, /* Role Switch Pending */
188 MGMT_STATUS_FAILED, /* Slot Violation */
189 MGMT_STATUS_FAILED, /* Role Switch Failed */
190 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
191 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
192 MGMT_STATUS_BUSY, /* Host Busy Pairing */
193 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
194 MGMT_STATUS_BUSY, /* Controller Busy */
195 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
196 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
197 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
198 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
199 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
200};
201
202static u8 mgmt_status(u8 hci_status)
203{
204 if (hci_status < ARRAY_SIZE(mgmt_status_table))
205 return mgmt_status_table[hci_status];
206
207 return MGMT_STATUS_FAILED;
208}
209
Szymon Janc4e51eae2011-02-25 19:05:48 +0100210static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200211{
212 struct sk_buff *skb;
213 struct mgmt_hdr *hdr;
214 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300215 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200216
Szymon Janc34eb5252011-02-28 14:10:08 +0100217 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200218
Andre Guedes790eff42012-06-07 19:05:46 -0300219 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200220 if (!skb)
221 return -ENOMEM;
222
223 hdr = (void *) skb_put(skb, sizeof(*hdr));
224
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700225 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100226 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200227 hdr->len = cpu_to_le16(sizeof(*ev));
228
229 ev = (void *) skb_put(skb, sizeof(*ev));
230 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200231 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200232
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300233 err = sock_queue_rcv_skb(sk, skb);
234 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200235 kfree_skb(skb);
236
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300237 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200238}
239
Johan Hedbergaee9b212012-02-18 15:07:59 +0200240static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300241 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200242{
243 struct sk_buff *skb;
244 struct mgmt_hdr *hdr;
245 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300246 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200247
248 BT_DBG("sock %p", sk);
249
Andre Guedes790eff42012-06-07 19:05:46 -0300250 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200251 if (!skb)
252 return -ENOMEM;
253
254 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200255
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700256 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100257 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200258 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200259
Johan Hedberga38528f2011-01-22 06:46:43 +0200260 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200261 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200262 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100263
264 if (rp)
265 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200266
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300267 err = sock_queue_rcv_skb(sk, skb);
268 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200269 kfree_skb(skb);
270
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100271 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200272}
273
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300274static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
275 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200276{
277 struct mgmt_rp_read_version rp;
278
279 BT_DBG("sock %p", sk);
280
281 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700282 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200283
Johan Hedbergaee9b212012-02-18 15:07:59 +0200284 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300285 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200286}
287
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300288static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
289 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200290{
291 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200292 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
293 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200294 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200295 size_t rp_size;
296 int i, err;
297
298 BT_DBG("sock %p", sk);
299
300 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
301
302 rp = kmalloc(rp_size, GFP_KERNEL);
303 if (!rp)
304 return -ENOMEM;
305
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700306 rp->num_commands = cpu_to_le16(num_commands);
307 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200308
309 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
310 put_unaligned_le16(mgmt_commands[i], opcode);
311
312 for (i = 0; i < num_events; i++, opcode++)
313 put_unaligned_le16(mgmt_events[i], opcode);
314
Johan Hedbergaee9b212012-02-18 15:07:59 +0200315 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300316 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200317 kfree(rp);
318
319 return err;
320}
321
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
323 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200324{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200325 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200326 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200327 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300329 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200330
331 BT_DBG("sock %p", sk);
332
333 read_lock(&hci_dev_list_lock);
334
335 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300336 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700337 if (d->dev_type == HCI_BREDR)
338 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339 }
340
Johan Hedberga38528f2011-01-22 06:46:43 +0200341 rp_len = sizeof(*rp) + (2 * count);
342 rp = kmalloc(rp_len, GFP_ATOMIC);
343 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100344 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200345 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100346 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200347
Johan Hedberg476e44c2012-10-19 20:10:46 +0300348 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200349 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200350 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200351 continue;
352
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700353 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
354 continue;
355
Marcel Holtmannfee746b2014-06-29 12:13:05 +0200356 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
357 continue;
358
Marcel Holtmann1514b892013-10-06 08:25:01 -0700359 if (d->dev_type == HCI_BREDR) {
360 rp->index[count++] = cpu_to_le16(d->id);
361 BT_DBG("Added hci%u", d->id);
362 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363 }
364
Johan Hedberg476e44c2012-10-19 20:10:46 +0300365 rp->num_controllers = cpu_to_le16(count);
366 rp_len = sizeof(*rp) + (2 * count);
367
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200368 read_unlock(&hci_dev_list_lock);
369
Johan Hedbergaee9b212012-02-18 15:07:59 +0200370 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300371 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200372
Johan Hedberga38528f2011-01-22 06:46:43 +0200373 kfree(rp);
374
375 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200376}
377
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200378static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200379{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200380 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200381
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200382 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200383 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800384 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200385
Andre Guedesed3fa312012-07-24 15:03:46 -0300386 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300387 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500388 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
389 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300390 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200391 settings |= MGMT_SETTING_BREDR;
392 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700393
394 if (lmp_ssp_capable(hdev)) {
395 settings |= MGMT_SETTING_SSP;
396 settings |= MGMT_SETTING_HS;
397 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800398
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800399 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200400 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800401 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700402 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100403
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300404 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200405 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300406 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200407 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300408 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200409
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200410 return settings;
411}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200412
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200413static u32 get_current_settings(struct hci_dev *hdev)
414{
415 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200416
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200417 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100418 settings |= MGMT_SETTING_POWERED;
419
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200420 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200421 settings |= MGMT_SETTING_CONNECTABLE;
422
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500423 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
424 settings |= MGMT_SETTING_FAST_CONNECTABLE;
425
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200426 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200427 settings |= MGMT_SETTING_DISCOVERABLE;
428
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200429 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200430 settings |= MGMT_SETTING_PAIRABLE;
431
Johan Hedberg56f87902013-10-02 13:43:13 +0300432 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200433 settings |= MGMT_SETTING_BREDR;
434
Johan Hedberg06199cf2012-02-22 16:37:11 +0200435 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200436 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200437
Johan Hedberg47990ea2012-02-22 11:58:37 +0200438 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200439 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200440
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200441 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200442 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200443
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200444 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
445 settings |= MGMT_SETTING_HS;
446
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200447 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300448 settings |= MGMT_SETTING_ADVERTISING;
449
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800450 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
451 settings |= MGMT_SETTING_SECURE_CONN;
452
Johan Hedberg0663b292014-06-24 13:15:50 +0300453 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800454 settings |= MGMT_SETTING_DEBUG_KEYS;
455
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200456 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
457 settings |= MGMT_SETTING_PRIVACY;
458
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200459 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200460}
461
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300462#define PNP_INFO_SVCLASS_ID 0x1200
463
Johan Hedberg213202e2013-01-27 00:31:33 +0200464static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
465{
466 u8 *ptr = data, *uuids_start = NULL;
467 struct bt_uuid *uuid;
468
469 if (len < 4)
470 return ptr;
471
472 list_for_each_entry(uuid, &hdev->uuids, list) {
473 u16 uuid16;
474
475 if (uuid->size != 16)
476 continue;
477
478 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
479 if (uuid16 < 0x1100)
480 continue;
481
482 if (uuid16 == PNP_INFO_SVCLASS_ID)
483 continue;
484
485 if (!uuids_start) {
486 uuids_start = ptr;
487 uuids_start[0] = 1;
488 uuids_start[1] = EIR_UUID16_ALL;
489 ptr += 2;
490 }
491
492 /* Stop if not enough space to put next UUID */
493 if ((ptr - data) + sizeof(u16) > len) {
494 uuids_start[1] = EIR_UUID16_SOME;
495 break;
496 }
497
498 *ptr++ = (uuid16 & 0x00ff);
499 *ptr++ = (uuid16 & 0xff00) >> 8;
500 uuids_start[0] += sizeof(uuid16);
501 }
502
503 return ptr;
504}
505
Johan Hedbergcdf19632013-01-27 00:31:34 +0200506static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
507{
508 u8 *ptr = data, *uuids_start = NULL;
509 struct bt_uuid *uuid;
510
511 if (len < 6)
512 return ptr;
513
514 list_for_each_entry(uuid, &hdev->uuids, list) {
515 if (uuid->size != 32)
516 continue;
517
518 if (!uuids_start) {
519 uuids_start = ptr;
520 uuids_start[0] = 1;
521 uuids_start[1] = EIR_UUID32_ALL;
522 ptr += 2;
523 }
524
525 /* Stop if not enough space to put next UUID */
526 if ((ptr - data) + sizeof(u32) > len) {
527 uuids_start[1] = EIR_UUID32_SOME;
528 break;
529 }
530
531 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
532 ptr += sizeof(u32);
533 uuids_start[0] += sizeof(u32);
534 }
535
536 return ptr;
537}
538
Johan Hedbergc00d5752013-01-27 00:31:35 +0200539static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
540{
541 u8 *ptr = data, *uuids_start = NULL;
542 struct bt_uuid *uuid;
543
544 if (len < 18)
545 return ptr;
546
547 list_for_each_entry(uuid, &hdev->uuids, list) {
548 if (uuid->size != 128)
549 continue;
550
551 if (!uuids_start) {
552 uuids_start = ptr;
553 uuids_start[0] = 1;
554 uuids_start[1] = EIR_UUID128_ALL;
555 ptr += 2;
556 }
557
558 /* Stop if not enough space to put next UUID */
559 if ((ptr - data) + 16 > len) {
560 uuids_start[1] = EIR_UUID128_SOME;
561 break;
562 }
563
564 memcpy(ptr, uuid->uuid, 16);
565 ptr += 16;
566 uuids_start[0] += 16;
567 }
568
569 return ptr;
570}
571
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300572static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
573{
574 struct pending_cmd *cmd;
575
576 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
577 if (cmd->opcode == opcode)
578 return cmd;
579 }
580
581 return NULL;
582}
583
Johan Hedberg95868422014-06-28 17:54:07 +0300584static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
585 struct hci_dev *hdev,
586 const void *data)
587{
588 struct pending_cmd *cmd;
589
590 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
591 if (cmd->user_data != data)
592 continue;
593 if (cmd->opcode == opcode)
594 return cmd;
595 }
596
597 return NULL;
598}
599
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700600static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
601{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700602 u8 ad_len = 0;
603 size_t name_len;
604
605 name_len = strlen(hdev->dev_name);
606 if (name_len > 0) {
607 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
608
609 if (name_len > max_len) {
610 name_len = max_len;
611 ptr[1] = EIR_NAME_SHORT;
612 } else
613 ptr[1] = EIR_NAME_COMPLETE;
614
615 ptr[0] = name_len + 1;
616
617 memcpy(ptr + 2, hdev->dev_name, name_len);
618
619 ad_len += (name_len + 2);
620 ptr += (name_len + 2);
621 }
622
623 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700624}
625
626static void update_scan_rsp_data(struct hci_request *req)
627{
628 struct hci_dev *hdev = req->hdev;
629 struct hci_cp_le_set_scan_rsp_data cp;
630 u8 len;
631
Johan Hedberg7751ef12013-10-19 23:38:15 +0300632 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700633 return;
634
635 memset(&cp, 0, sizeof(cp));
636
637 len = create_scan_rsp_data(hdev, cp.data);
638
Johan Hedbergeb438b52013-10-16 15:31:07 +0300639 if (hdev->scan_rsp_data_len == len &&
640 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700641 return;
642
Johan Hedbergeb438b52013-10-16 15:31:07 +0300643 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
644 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700645
646 cp.length = len;
647
648 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
649}
650
Johan Hedberg9a43e252013-10-20 19:00:07 +0300651static u8 get_adv_discov_flags(struct hci_dev *hdev)
652{
653 struct pending_cmd *cmd;
654
655 /* If there's a pending mgmt command the flags will not yet have
656 * their final values, so check for this first.
657 */
658 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
659 if (cmd) {
660 struct mgmt_mode *cp = cmd->param;
661 if (cp->val == 0x01)
662 return LE_AD_GENERAL;
663 else if (cp->val == 0x02)
664 return LE_AD_LIMITED;
665 } else {
666 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
667 return LE_AD_LIMITED;
668 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
669 return LE_AD_GENERAL;
670 }
671
672 return 0;
673}
674
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700675static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700676{
677 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678
Johan Hedberg9a43e252013-10-20 19:00:07 +0300679 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700680
Johan Hedberge8340042014-01-30 11:16:50 -0800681 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700683
684 if (flags) {
685 BT_DBG("adv flags 0x%02x", flags);
686
687 ptr[0] = 2;
688 ptr[1] = EIR_FLAGS;
689 ptr[2] = flags;
690
691 ad_len += 3;
692 ptr += 3;
693 }
694
695 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
696 ptr[0] = 2;
697 ptr[1] = EIR_TX_POWER;
698 ptr[2] = (u8) hdev->adv_tx_power;
699
700 ad_len += 3;
701 ptr += 3;
702 }
703
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700704 return ad_len;
705}
706
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700707static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700708{
709 struct hci_dev *hdev = req->hdev;
710 struct hci_cp_le_set_adv_data cp;
711 u8 len;
712
Johan Hedberg10994ce2013-10-19 23:38:16 +0300713 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700714 return;
715
716 memset(&cp, 0, sizeof(cp));
717
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700718 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700719
720 if (hdev->adv_data_len == len &&
721 memcmp(cp.data, hdev->adv_data, len) == 0)
722 return;
723
724 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
725 hdev->adv_data_len = len;
726
727 cp.length = len;
728
729 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
730}
731
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300732static void create_eir(struct hci_dev *hdev, u8 *data)
733{
734 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300735 size_t name_len;
736
737 name_len = strlen(hdev->dev_name);
738
739 if (name_len > 0) {
740 /* EIR Data type */
741 if (name_len > 48) {
742 name_len = 48;
743 ptr[1] = EIR_NAME_SHORT;
744 } else
745 ptr[1] = EIR_NAME_COMPLETE;
746
747 /* EIR Data length */
748 ptr[0] = name_len + 1;
749
750 memcpy(ptr + 2, hdev->dev_name, name_len);
751
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752 ptr += (name_len + 2);
753 }
754
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100755 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700756 ptr[0] = 2;
757 ptr[1] = EIR_TX_POWER;
758 ptr[2] = (u8) hdev->inq_tx_power;
759
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700760 ptr += 3;
761 }
762
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700763 if (hdev->devid_source > 0) {
764 ptr[0] = 9;
765 ptr[1] = EIR_DEVICE_ID;
766
767 put_unaligned_le16(hdev->devid_source, ptr + 2);
768 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
769 put_unaligned_le16(hdev->devid_product, ptr + 6);
770 put_unaligned_le16(hdev->devid_version, ptr + 8);
771
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700772 ptr += 10;
773 }
774
Johan Hedberg213202e2013-01-27 00:31:33 +0200775 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200776 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200777 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300778}
779
Johan Hedberg890ea892013-03-15 17:06:52 -0500780static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781{
Johan Hedberg890ea892013-03-15 17:06:52 -0500782 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300783 struct hci_cp_write_eir cp;
784
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200785 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500786 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200787
Johan Hedberg976eb202012-10-24 21:12:01 +0300788 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500789 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300790
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200791 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500792 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300793
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200794 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500795 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300796
797 memset(&cp, 0, sizeof(cp));
798
799 create_eir(hdev, cp.data);
800
801 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500802 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300803
804 memcpy(hdev->eir, cp.data, sizeof(cp.data));
805
Johan Hedberg890ea892013-03-15 17:06:52 -0500806 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300807}
808
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809static u8 get_service_classes(struct hci_dev *hdev)
810{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300811 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200812 u8 val = 0;
813
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300814 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200815 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200816
817 return val;
818}
819
Johan Hedberg890ea892013-03-15 17:06:52 -0500820static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821{
Johan Hedberg890ea892013-03-15 17:06:52 -0500822 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200823 u8 cod[3];
824
825 BT_DBG("%s", hdev->name);
826
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200827 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500828 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200829
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300830 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
831 return;
832
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200833 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500834 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200835
836 cod[0] = hdev->minor_class;
837 cod[1] = hdev->major_class;
838 cod[2] = get_service_classes(hdev);
839
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700840 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
841 cod[1] |= 0x20;
842
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200843 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500844 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200845
Johan Hedberg890ea892013-03-15 17:06:52 -0500846 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200847}
848
Johan Hedberga4858cb2014-02-25 19:56:31 +0200849static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200850{
851 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200852
853 /* If there's a pending mgmt command the flag will not yet have
854 * it's final value, so check for this first.
855 */
856 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
857 if (cmd) {
858 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200859 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200860 }
861
Johan Hedberga4858cb2014-02-25 19:56:31 +0200862 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200863}
864
865static void enable_advertising(struct hci_request *req)
866{
867 struct hci_dev *hdev = req->hdev;
868 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200869 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200870 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200871
Johan Hedberg8d972502014-02-28 12:54:14 +0200872 /* Clear the HCI_ADVERTISING bit temporarily so that the
873 * hci_update_random_address knows that it's safe to go ahead
874 * and write a new random address. The flag will be set back on
875 * as soon as the SET_ADV_ENABLE HCI command completes.
876 */
877 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
878
Johan Hedberga4858cb2014-02-25 19:56:31 +0200879 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200880
Johan Hedberga4858cb2014-02-25 19:56:31 +0200881 /* Set require_privacy to true only when non-connectable
882 * advertising is used. In that case it is fine to use a
883 * non-resolvable private address.
884 */
885 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200886 return;
887
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800888 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700889 cp.min_interval = cpu_to_le16(0x0800);
890 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200891 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200892 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200893 cp.channel_map = hdev->le_adv_channel_map;
894
895 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
896
897 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
898}
899
900static void disable_advertising(struct hci_request *req)
901{
902 u8 enable = 0x00;
903
904 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
905}
906
Johan Hedberg7d785252011-12-15 00:47:39 +0200907static void service_cache_off(struct work_struct *work)
908{
909 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300910 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500911 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200912
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200913 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200914 return;
915
Johan Hedberg890ea892013-03-15 17:06:52 -0500916 hci_req_init(&req, hdev);
917
Johan Hedberg7d785252011-12-15 00:47:39 +0200918 hci_dev_lock(hdev);
919
Johan Hedberg890ea892013-03-15 17:06:52 -0500920 update_eir(&req);
921 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200922
923 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500924
925 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200926}
927
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200928static void rpa_expired(struct work_struct *work)
929{
930 struct hci_dev *hdev = container_of(work, struct hci_dev,
931 rpa_expired.work);
932 struct hci_request req;
933
934 BT_DBG("");
935
936 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
937
938 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
939 hci_conn_num(hdev, LE_LINK) > 0)
940 return;
941
942 /* The generation of a new RPA and programming it into the
943 * controller happens in the enable_advertising() function.
944 */
945
946 hci_req_init(&req, hdev);
947
948 disable_advertising(&req);
949 enable_advertising(&req);
950
951 hci_req_run(&req, NULL);
952}
953
Johan Hedberg6a919082012-02-28 06:17:26 +0200954static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200955{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200956 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200957 return;
958
Johan Hedberg4f87da82012-03-02 19:55:56 +0200959 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200960 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200961
Johan Hedberg4f87da82012-03-02 19:55:56 +0200962 /* Non-mgmt controlled devices get this bit set
963 * implicitly so that pairing works for them, however
964 * for mgmt we require user-space to explicitly enable
965 * it
966 */
967 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200968}
969
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200970static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200972{
973 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200974
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200975 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200976
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300977 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200978
Johan Hedberg03811012010-12-08 00:21:06 +0200979 memset(&rp, 0, sizeof(rp));
980
Johan Hedberg03811012010-12-08 00:21:06 +0200981 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200982
983 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200984 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200985
986 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
987 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
988
989 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200990
991 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200992 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200993
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300994 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200995
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200996 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300997 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200998}
999
1000static void mgmt_pending_free(struct pending_cmd *cmd)
1001{
1002 sock_put(cmd->sk);
1003 kfree(cmd->param);
1004 kfree(cmd);
1005}
1006
1007static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001008 struct hci_dev *hdev, void *data,
1009 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001010{
1011 struct pending_cmd *cmd;
1012
Johan Hedbergfca20012014-06-28 17:54:05 +03001013 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001014 if (!cmd)
1015 return NULL;
1016
1017 cmd->opcode = opcode;
1018 cmd->index = hdev->id;
1019
Andre Guedes12b94562012-06-07 19:05:45 -03001020 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001021 if (!cmd->param) {
1022 kfree(cmd);
1023 return NULL;
1024 }
1025
1026 if (data)
1027 memcpy(cmd->param, data, len);
1028
1029 cmd->sk = sk;
1030 sock_hold(sk);
1031
1032 list_add(&cmd->list, &hdev->mgmt_pending);
1033
1034 return cmd;
1035}
1036
1037static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001038 void (*cb)(struct pending_cmd *cmd,
1039 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001040 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001041{
Andre Guedesa3d09352013-02-01 11:21:30 -03001042 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001043
Andre Guedesa3d09352013-02-01 11:21:30 -03001044 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001045 if (opcode > 0 && cmd->opcode != opcode)
1046 continue;
1047
1048 cb(cmd, data);
1049 }
1050}
1051
Johan Hedberg03811012010-12-08 00:21:06 +02001052static void mgmt_pending_remove(struct pending_cmd *cmd)
1053{
1054 list_del(&cmd->list);
1055 mgmt_pending_free(cmd);
1056}
1057
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001058static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001059{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001060 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001061
Johan Hedbergaee9b212012-02-18 15:07:59 +02001062 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001063 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001064}
1065
Johan Hedberg8b064a32014-02-24 14:52:22 +02001066static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1067{
1068 BT_DBG("%s status 0x%02x", hdev->name, status);
1069
Johan Hedberga3172b72014-02-28 09:33:44 +02001070 if (hci_conn_count(hdev) == 0) {
1071 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001072 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001073 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001074}
1075
Johan Hedberg21a60d32014-06-10 14:05:58 +03001076static void hci_stop_discovery(struct hci_request *req)
1077{
1078 struct hci_dev *hdev = req->hdev;
1079 struct hci_cp_remote_name_req_cancel cp;
1080 struct inquiry_entry *e;
1081
1082 switch (hdev->discovery.state) {
1083 case DISCOVERY_FINDING:
1084 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1085 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1086 } else {
1087 cancel_delayed_work(&hdev->le_scan_disable);
1088 hci_req_add_le_scan_disable(req);
1089 }
1090
1091 break;
1092
1093 case DISCOVERY_RESOLVING:
1094 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1095 NAME_PENDING);
1096 if (!e)
1097 return;
1098
1099 bacpy(&cp.bdaddr, &e->data.bdaddr);
1100 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1101 &cp);
1102
1103 break;
1104
1105 default:
1106 /* Passive scanning */
1107 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1108 hci_req_add_le_scan_disable(req);
1109 break;
1110 }
1111}
1112
Johan Hedberg8b064a32014-02-24 14:52:22 +02001113static int clean_up_hci_state(struct hci_dev *hdev)
1114{
1115 struct hci_request req;
1116 struct hci_conn *conn;
1117
1118 hci_req_init(&req, hdev);
1119
1120 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1121 test_bit(HCI_PSCAN, &hdev->flags)) {
1122 u8 scan = 0x00;
1123 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1124 }
1125
1126 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1127 disable_advertising(&req);
1128
Johan Hedbergf8680f12014-06-10 14:05:59 +03001129 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001130
1131 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1132 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001133 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001134
Johan Hedbergc9910d02014-02-27 14:35:12 +02001135 switch (conn->state) {
1136 case BT_CONNECTED:
1137 case BT_CONFIG:
1138 dc.handle = cpu_to_le16(conn->handle);
1139 dc.reason = 0x15; /* Terminated due to Power Off */
1140 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1141 break;
1142 case BT_CONNECT:
1143 if (conn->type == LE_LINK)
1144 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1145 0, NULL);
1146 else if (conn->type == ACL_LINK)
1147 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1148 6, &conn->dst);
1149 break;
1150 case BT_CONNECT2:
1151 bacpy(&rej.bdaddr, &conn->dst);
1152 rej.reason = 0x15; /* Terminated due to Power Off */
1153 if (conn->type == ACL_LINK)
1154 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1155 sizeof(rej), &rej);
1156 else if (conn->type == SCO_LINK)
1157 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1158 sizeof(rej), &rej);
1159 break;
1160 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001161 }
1162
1163 return hci_req_run(&req, clean_up_hci_complete);
1164}
1165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001166static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001167 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001168{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001169 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001170 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001171 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001173 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001174
Johan Hedberga7e80f22013-01-09 16:05:19 +02001175 if (cp->val != 0x00 && cp->val != 0x01)
1176 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1177 MGMT_STATUS_INVALID_PARAMS);
1178
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001179 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001180
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001181 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1182 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1183 MGMT_STATUS_BUSY);
1184 goto failed;
1185 }
1186
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001187 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1188 cancel_delayed_work(&hdev->power_off);
1189
1190 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001191 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1192 data, len);
1193 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001194 goto failed;
1195 }
1196 }
1197
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001198 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001199 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001200 goto failed;
1201 }
1202
Johan Hedberg03811012010-12-08 00:21:06 +02001203 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1204 if (!cmd) {
1205 err = -ENOMEM;
1206 goto failed;
1207 }
1208
Johan Hedberg8b064a32014-02-24 14:52:22 +02001209 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001210 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001211 err = 0;
1212 } else {
1213 /* Disconnect connections, stop scans, etc */
1214 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001215 if (!err)
1216 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1217 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001218
Johan Hedberg8b064a32014-02-24 14:52:22 +02001219 /* ENODATA means there were no HCI commands queued */
1220 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001221 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001222 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1223 err = 0;
1224 }
1225 }
Johan Hedberg03811012010-12-08 00:21:06 +02001226
1227failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001228 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001229 return err;
1230}
1231
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001232static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1233 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001234{
1235 struct sk_buff *skb;
1236 struct mgmt_hdr *hdr;
1237
Andre Guedes790eff42012-06-07 19:05:46 -03001238 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001239 if (!skb)
1240 return -ENOMEM;
1241
1242 hdr = (void *) skb_put(skb, sizeof(*hdr));
1243 hdr->opcode = cpu_to_le16(event);
1244 if (hdev)
1245 hdr->index = cpu_to_le16(hdev->id);
1246 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001247 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001248 hdr->len = cpu_to_le16(data_len);
1249
1250 if (data)
1251 memcpy(skb_put(skb, data_len), data, data_len);
1252
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001253 /* Time stamp */
1254 __net_timestamp(skb);
1255
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001256 hci_send_to_control(skb, skip_sk);
1257 kfree_skb(skb);
1258
1259 return 0;
1260}
1261
1262static int new_settings(struct hci_dev *hdev, struct sock *skip)
1263{
1264 __le32 ev;
1265
1266 ev = cpu_to_le32(get_current_settings(hdev));
1267
1268 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1269}
1270
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001271struct cmd_lookup {
1272 struct sock *sk;
1273 struct hci_dev *hdev;
1274 u8 mgmt_status;
1275};
1276
1277static void settings_rsp(struct pending_cmd *cmd, void *data)
1278{
1279 struct cmd_lookup *match = data;
1280
1281 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1282
1283 list_del(&cmd->list);
1284
1285 if (match->sk == NULL) {
1286 match->sk = cmd->sk;
1287 sock_hold(match->sk);
1288 }
1289
1290 mgmt_pending_free(cmd);
1291}
1292
1293static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1294{
1295 u8 *status = data;
1296
1297 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1298 mgmt_pending_remove(cmd);
1299}
1300
Johan Hedberge6fe7982013-10-02 15:45:22 +03001301static u8 mgmt_bredr_support(struct hci_dev *hdev)
1302{
1303 if (!lmp_bredr_capable(hdev))
1304 return MGMT_STATUS_NOT_SUPPORTED;
1305 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1306 return MGMT_STATUS_REJECTED;
1307 else
1308 return MGMT_STATUS_SUCCESS;
1309}
1310
1311static u8 mgmt_le_support(struct hci_dev *hdev)
1312{
1313 if (!lmp_le_capable(hdev))
1314 return MGMT_STATUS_NOT_SUPPORTED;
1315 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1316 return MGMT_STATUS_REJECTED;
1317 else
1318 return MGMT_STATUS_SUCCESS;
1319}
1320
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001321static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1322{
1323 struct pending_cmd *cmd;
1324 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001325 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001326 bool changed;
1327
1328 BT_DBG("status 0x%02x", status);
1329
1330 hci_dev_lock(hdev);
1331
1332 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1333 if (!cmd)
1334 goto unlock;
1335
1336 if (status) {
1337 u8 mgmt_err = mgmt_status(status);
1338 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001339 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001340 goto remove_cmd;
1341 }
1342
1343 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001344 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001345 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1346 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001347
1348 if (hdev->discov_timeout > 0) {
1349 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1350 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1351 to);
1352 }
1353 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001354 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1355 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001356 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001357
1358 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1359
1360 if (changed)
1361 new_settings(hdev, cmd->sk);
1362
Marcel Holtmann970ba522013-10-15 06:33:57 -07001363 /* When the discoverable mode gets changed, make sure
1364 * that class of device has the limited discoverable
1365 * bit correctly set.
1366 */
1367 hci_req_init(&req, hdev);
1368 update_class(&req);
1369 hci_req_run(&req, NULL);
1370
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001371remove_cmd:
1372 mgmt_pending_remove(cmd);
1373
1374unlock:
1375 hci_dev_unlock(hdev);
1376}
1377
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001378static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001379 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001380{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001381 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001382 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001383 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001384 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001385 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001386 int err;
1387
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001388 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001389
Johan Hedberg9a43e252013-10-20 19:00:07 +03001390 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1391 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001392 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001393 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001394
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001395 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001396 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1397 MGMT_STATUS_INVALID_PARAMS);
1398
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001399 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001400
1401 /* Disabling discoverable requires that no timeout is set,
1402 * and enabling limited discoverable requires a timeout.
1403 */
1404 if ((cp->val == 0x00 && timeout > 0) ||
1405 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001406 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001407 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001408
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001409 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001410
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001411 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001412 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001413 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001414 goto failed;
1415 }
1416
1417 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001418 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001419 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001420 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001421 goto failed;
1422 }
1423
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001424 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001425 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001426 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001427 goto failed;
1428 }
1429
1430 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001431 bool changed = false;
1432
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001433 /* Setting limited discoverable when powered off is
1434 * not a valid operation since it requires a timeout
1435 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1436 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001437 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1438 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1439 changed = true;
1440 }
1441
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001442 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001443 if (err < 0)
1444 goto failed;
1445
1446 if (changed)
1447 err = new_settings(hdev, sk);
1448
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001449 goto failed;
1450 }
1451
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001452 /* If the current mode is the same, then just update the timeout
1453 * value with the new value. And if only the timeout gets updated,
1454 * then no need for any HCI transactions.
1455 */
1456 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1457 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1458 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001459 cancel_delayed_work(&hdev->discov_off);
1460 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001461
Marcel Holtmann36261542013-10-15 08:28:51 -07001462 if (cp->val && hdev->discov_timeout > 0) {
1463 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001464 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001465 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001466 }
1467
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001468 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001469 goto failed;
1470 }
1471
1472 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1473 if (!cmd) {
1474 err = -ENOMEM;
1475 goto failed;
1476 }
1477
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001478 /* Cancel any potential discoverable timeout that might be
1479 * still active and store new timeout value. The arming of
1480 * the timeout happens in the complete handler.
1481 */
1482 cancel_delayed_work(&hdev->discov_off);
1483 hdev->discov_timeout = timeout;
1484
Johan Hedbergb456f872013-10-19 23:38:22 +03001485 /* Limited discoverable mode */
1486 if (cp->val == 0x02)
1487 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1488 else
1489 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1490
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001491 hci_req_init(&req, hdev);
1492
Johan Hedberg9a43e252013-10-20 19:00:07 +03001493 /* The procedure for LE-only controllers is much simpler - just
1494 * update the advertising data.
1495 */
1496 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1497 goto update_ad;
1498
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001499 scan = SCAN_PAGE;
1500
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001501 if (cp->val) {
1502 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001503
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001504 if (cp->val == 0x02) {
1505 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001506 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001507 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1508 hci_cp.iac_lap[1] = 0x8b;
1509 hci_cp.iac_lap[2] = 0x9e;
1510 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1511 hci_cp.iac_lap[4] = 0x8b;
1512 hci_cp.iac_lap[5] = 0x9e;
1513 } else {
1514 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001515 hci_cp.num_iac = 1;
1516 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1517 hci_cp.iac_lap[1] = 0x8b;
1518 hci_cp.iac_lap[2] = 0x9e;
1519 }
1520
1521 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1522 (hci_cp.num_iac * 3) + 1, &hci_cp);
1523
1524 scan |= SCAN_INQUIRY;
1525 } else {
1526 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1527 }
1528
1529 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001530
Johan Hedberg9a43e252013-10-20 19:00:07 +03001531update_ad:
1532 update_adv_data(&req);
1533
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001534 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001535 if (err < 0)
1536 mgmt_pending_remove(cmd);
1537
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001538failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001539 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001540 return err;
1541}
1542
Johan Hedberg406d7802013-03-15 17:07:09 -05001543static void write_fast_connectable(struct hci_request *req, bool enable)
1544{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001545 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001546 struct hci_cp_write_page_scan_activity acp;
1547 u8 type;
1548
Johan Hedberg547003b2013-10-21 16:51:53 +03001549 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1550 return;
1551
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001552 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1553 return;
1554
Johan Hedberg406d7802013-03-15 17:07:09 -05001555 if (enable) {
1556 type = PAGE_SCAN_TYPE_INTERLACED;
1557
1558 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001559 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001560 } else {
1561 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1562
1563 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001564 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001565 }
1566
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001567 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001568
Johan Hedbergbd98b992013-03-15 17:07:13 -05001569 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1570 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1571 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1572 sizeof(acp), &acp);
1573
1574 if (hdev->page_scan_type != type)
1575 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001576}
1577
Johan Hedberg2b76f452013-03-15 17:07:04 -05001578static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1579{
1580 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001581 struct mgmt_mode *cp;
1582 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001583
1584 BT_DBG("status 0x%02x", status);
1585
1586 hci_dev_lock(hdev);
1587
1588 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1589 if (!cmd)
1590 goto unlock;
1591
Johan Hedberg37438c12013-10-14 16:20:05 +03001592 if (status) {
1593 u8 mgmt_err = mgmt_status(status);
1594 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1595 goto remove_cmd;
1596 }
1597
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001598 cp = cmd->param;
1599 if (cp->val)
1600 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1601 else
1602 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603
Johan Hedberg2b76f452013-03-15 17:07:04 -05001604 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1605
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001606 if (changed)
1607 new_settings(hdev, cmd->sk);
1608
Johan Hedberg37438c12013-10-14 16:20:05 +03001609remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001610 mgmt_pending_remove(cmd);
1611
1612unlock:
1613 hci_dev_unlock(hdev);
1614}
1615
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001616static int set_connectable_update_settings(struct hci_dev *hdev,
1617 struct sock *sk, u8 val)
1618{
1619 bool changed = false;
1620 int err;
1621
1622 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1623 changed = true;
1624
1625 if (val) {
1626 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1627 } else {
1628 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1629 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1630 }
1631
1632 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1633 if (err < 0)
1634 return err;
1635
1636 if (changed)
1637 return new_settings(hdev, sk);
1638
1639 return 0;
1640}
1641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001642static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001643 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001644{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001645 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001646 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001647 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001648 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001649 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001650
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001651 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001652
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001653 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1654 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001655 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001656 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001657
Johan Hedberga7e80f22013-01-09 16:05:19 +02001658 if (cp->val != 0x00 && cp->val != 0x01)
1659 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1660 MGMT_STATUS_INVALID_PARAMS);
1661
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001662 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001663
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001664 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001665 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001666 goto failed;
1667 }
1668
1669 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001670 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001671 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001672 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001673 goto failed;
1674 }
1675
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001676 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1677 if (!cmd) {
1678 err = -ENOMEM;
1679 goto failed;
1680 }
1681
Johan Hedberg2b76f452013-03-15 17:07:04 -05001682 hci_req_init(&req, hdev);
1683
Johan Hedberg9a43e252013-10-20 19:00:07 +03001684 /* If BR/EDR is not enabled and we disable advertising as a
1685 * by-product of disabling connectable, we need to update the
1686 * advertising flags.
1687 */
1688 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1689 if (!cp->val) {
1690 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1691 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1692 }
1693 update_adv_data(&req);
1694 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001695 if (cp->val) {
1696 scan = SCAN_PAGE;
1697 } else {
1698 scan = 0;
1699
1700 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001701 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001702 cancel_delayed_work(&hdev->discov_off);
1703 }
1704
1705 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1706 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001707
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001708 /* If we're going from non-connectable to connectable or
1709 * vice-versa when fast connectable is enabled ensure that fast
1710 * connectable gets disabled. write_fast_connectable won't do
1711 * anything if the page scan parameters are already what they
1712 * should be.
1713 */
1714 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001715 write_fast_connectable(&req, false);
1716
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001717 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1718 hci_conn_num(hdev, LE_LINK) == 0) {
1719 disable_advertising(&req);
1720 enable_advertising(&req);
1721 }
1722
Johan Hedberg2b76f452013-03-15 17:07:04 -05001723 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001724 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001726 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001727 err = set_connectable_update_settings(hdev, sk,
1728 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001729 goto failed;
1730 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001731
1732failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001733 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734 return err;
1735}
1736
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001737static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001738 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001739{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001740 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001741 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001742 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001744 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001745
Johan Hedberga7e80f22013-01-09 16:05:19 +02001746 if (cp->val != 0x00 && cp->val != 0x01)
1747 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1748 MGMT_STATUS_INVALID_PARAMS);
1749
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001750 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001751
1752 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001753 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001754 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001755 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001756
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001757 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001758 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001759 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001760
Marcel Holtmann55594352013-10-06 16:11:57 -07001761 if (changed)
1762 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001763
Marcel Holtmann55594352013-10-06 16:11:57 -07001764unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001765 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001766 return err;
1767}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001768
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001769static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1770 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001771{
1772 struct mgmt_mode *cp = data;
1773 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001774 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001775 int err;
1776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001777 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001778
Johan Hedberge6fe7982013-10-02 15:45:22 +03001779 status = mgmt_bredr_support(hdev);
1780 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001781 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001782 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001783
Johan Hedberga7e80f22013-01-09 16:05:19 +02001784 if (cp->val != 0x00 && cp->val != 0x01)
1785 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1786 MGMT_STATUS_INVALID_PARAMS);
1787
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001788 hci_dev_lock(hdev);
1789
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001790 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001791 bool changed = false;
1792
1793 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001794 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001795 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1796 changed = true;
1797 }
1798
1799 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1800 if (err < 0)
1801 goto failed;
1802
1803 if (changed)
1804 err = new_settings(hdev, sk);
1805
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001806 goto failed;
1807 }
1808
1809 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001810 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001811 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001812 goto failed;
1813 }
1814
1815 val = !!cp->val;
1816
1817 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1818 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1819 goto failed;
1820 }
1821
1822 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1823 if (!cmd) {
1824 err = -ENOMEM;
1825 goto failed;
1826 }
1827
1828 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1829 if (err < 0) {
1830 mgmt_pending_remove(cmd);
1831 goto failed;
1832 }
1833
1834failed:
1835 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001836 return err;
1837}
1838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001839static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001840{
1841 struct mgmt_mode *cp = data;
1842 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001843 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001844 int err;
1845
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001846 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001847
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001848 status = mgmt_bredr_support(hdev);
1849 if (status)
1850 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1851
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001852 if (!lmp_ssp_capable(hdev))
1853 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1854 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001855
Johan Hedberga7e80f22013-01-09 16:05:19 +02001856 if (cp->val != 0x00 && cp->val != 0x01)
1857 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1858 MGMT_STATUS_INVALID_PARAMS);
1859
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001860 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001861
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001862 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001863 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001864
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001865 if (cp->val) {
1866 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1867 &hdev->dev_flags);
1868 } else {
1869 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1870 &hdev->dev_flags);
1871 if (!changed)
1872 changed = test_and_clear_bit(HCI_HS_ENABLED,
1873 &hdev->dev_flags);
1874 else
1875 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001876 }
1877
1878 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1879 if (err < 0)
1880 goto failed;
1881
1882 if (changed)
1883 err = new_settings(hdev, sk);
1884
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001885 goto failed;
1886 }
1887
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001888 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1889 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001890 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1891 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001892 goto failed;
1893 }
1894
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001895 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001896 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1897 goto failed;
1898 }
1899
1900 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1901 if (!cmd) {
1902 err = -ENOMEM;
1903 goto failed;
1904 }
1905
Johan Hedberg37699722014-06-24 14:00:27 +03001906 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1907 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1908 sizeof(cp->val), &cp->val);
1909
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001910 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001911 if (err < 0) {
1912 mgmt_pending_remove(cmd);
1913 goto failed;
1914 }
1915
1916failed:
1917 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001918 return err;
1919}
1920
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001921static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001922{
1923 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001924 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001925 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001926 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001927
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001928 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001929
Johan Hedberge6fe7982013-10-02 15:45:22 +03001930 status = mgmt_bredr_support(hdev);
1931 if (status)
1932 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001933
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001934 if (!lmp_ssp_capable(hdev))
1935 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1936 MGMT_STATUS_NOT_SUPPORTED);
1937
1938 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1939 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1940 MGMT_STATUS_REJECTED);
1941
Johan Hedberga7e80f22013-01-09 16:05:19 +02001942 if (cp->val != 0x00 && cp->val != 0x01)
1943 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1944 MGMT_STATUS_INVALID_PARAMS);
1945
Marcel Holtmannee392692013-10-01 22:59:23 -07001946 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001947
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001948 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001949 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001950 } else {
1951 if (hdev_is_powered(hdev)) {
1952 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1953 MGMT_STATUS_REJECTED);
1954 goto unlock;
1955 }
1956
Marcel Holtmannee392692013-10-01 22:59:23 -07001957 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001958 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001959
1960 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1961 if (err < 0)
1962 goto unlock;
1963
1964 if (changed)
1965 err = new_settings(hdev, sk);
1966
1967unlock:
1968 hci_dev_unlock(hdev);
1969 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001970}
1971
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001972static void le_enable_complete(struct hci_dev *hdev, u8 status)
1973{
1974 struct cmd_lookup match = { NULL, hdev };
1975
1976 if (status) {
1977 u8 mgmt_err = mgmt_status(status);
1978
1979 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1980 &mgmt_err);
1981 return;
1982 }
1983
1984 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1985
1986 new_settings(hdev, match.sk);
1987
1988 if (match.sk)
1989 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001990
1991 /* Make sure the controller has a good default for
1992 * advertising data. Restrict the update to when LE
1993 * has actually been enabled. During power on, the
1994 * update in powered_update_hci will take care of it.
1995 */
1996 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1997 struct hci_request req;
1998
1999 hci_dev_lock(hdev);
2000
2001 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002002 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002003 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002004 hci_req_run(&req, NULL);
2005
2006 hci_dev_unlock(hdev);
2007 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002008}
2009
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002010static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002011{
2012 struct mgmt_mode *cp = data;
2013 struct hci_cp_write_le_host_supported hci_cp;
2014 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002015 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002016 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002017 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002018
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002019 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002020
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002021 if (!lmp_le_capable(hdev))
2022 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2023 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002024
Johan Hedberga7e80f22013-01-09 16:05:19 +02002025 if (cp->val != 0x00 && cp->val != 0x01)
2026 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2027 MGMT_STATUS_INVALID_PARAMS);
2028
Johan Hedbergc73eee92013-04-19 18:35:21 +03002029 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002030 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002031 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2032 MGMT_STATUS_REJECTED);
2033
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002034 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002035
2036 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002037 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002038
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002039 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002040 bool changed = false;
2041
2042 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2043 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2044 changed = true;
2045 }
2046
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002047 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2048 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002049 changed = true;
2050 }
2051
Johan Hedberg06199cf2012-02-22 16:37:11 +02002052 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2053 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002054 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002055
2056 if (changed)
2057 err = new_settings(hdev, sk);
2058
Johan Hedberg1de028c2012-02-29 19:55:35 -08002059 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002060 }
2061
Johan Hedberg4375f102013-09-25 13:26:10 +03002062 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2063 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002064 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002065 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002066 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002067 }
2068
2069 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2070 if (!cmd) {
2071 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002072 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002073 }
2074
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002075 hci_req_init(&req, hdev);
2076
Johan Hedberg06199cf2012-02-22 16:37:11 +02002077 memset(&hci_cp, 0, sizeof(hci_cp));
2078
2079 if (val) {
2080 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002081 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002082 } else {
2083 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2084 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002085 }
2086
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002087 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2088 &hci_cp);
2089
2090 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302091 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002092 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002093
Johan Hedberg1de028c2012-02-29 19:55:35 -08002094unlock:
2095 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002096 return err;
2097}
2098
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002099/* This is a helper function to test for pending mgmt commands that can
2100 * cause CoD or EIR HCI commands. We can only allow one such pending
2101 * mgmt command at a time since otherwise we cannot easily track what
2102 * the current values are, will be, and based on that calculate if a new
2103 * HCI command needs to be sent and if yes with what value.
2104 */
2105static bool pending_eir_or_class(struct hci_dev *hdev)
2106{
2107 struct pending_cmd *cmd;
2108
2109 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2110 switch (cmd->opcode) {
2111 case MGMT_OP_ADD_UUID:
2112 case MGMT_OP_REMOVE_UUID:
2113 case MGMT_OP_SET_DEV_CLASS:
2114 case MGMT_OP_SET_POWERED:
2115 return true;
2116 }
2117 }
2118
2119 return false;
2120}
2121
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002122static const u8 bluetooth_base_uuid[] = {
2123 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2124 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2125};
2126
2127static u8 get_uuid_size(const u8 *uuid)
2128{
2129 u32 val;
2130
2131 if (memcmp(uuid, bluetooth_base_uuid, 12))
2132 return 128;
2133
2134 val = get_unaligned_le32(&uuid[12]);
2135 if (val > 0xffff)
2136 return 32;
2137
2138 return 16;
2139}
2140
Johan Hedberg92da6092013-03-15 17:06:55 -05002141static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2142{
2143 struct pending_cmd *cmd;
2144
2145 hci_dev_lock(hdev);
2146
2147 cmd = mgmt_pending_find(mgmt_op, hdev);
2148 if (!cmd)
2149 goto unlock;
2150
2151 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2152 hdev->dev_class, 3);
2153
2154 mgmt_pending_remove(cmd);
2155
2156unlock:
2157 hci_dev_unlock(hdev);
2158}
2159
2160static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2161{
2162 BT_DBG("status 0x%02x", status);
2163
2164 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2165}
2166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002167static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002168{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002169 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002170 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002171 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002172 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002173 int err;
2174
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002175 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002176
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002177 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002178
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002179 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002181 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002182 goto failed;
2183 }
2184
Andre Guedes92c4c202012-06-07 19:05:44 -03002185 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002186 if (!uuid) {
2187 err = -ENOMEM;
2188 goto failed;
2189 }
2190
2191 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002192 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002193 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002194
Johan Hedbergde66aa62013-01-27 00:31:27 +02002195 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002196
Johan Hedberg890ea892013-03-15 17:06:52 -05002197 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002198
Johan Hedberg890ea892013-03-15 17:06:52 -05002199 update_class(&req);
2200 update_eir(&req);
2201
Johan Hedberg92da6092013-03-15 17:06:55 -05002202 err = hci_req_run(&req, add_uuid_complete);
2203 if (err < 0) {
2204 if (err != -ENODATA)
2205 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002207 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002208 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002209 goto failed;
2210 }
2211
2212 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002213 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002214 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002215 goto failed;
2216 }
2217
2218 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002219
2220failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002221 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002222 return err;
2223}
2224
Johan Hedberg24b78d02012-02-23 23:24:30 +02002225static bool enable_service_cache(struct hci_dev *hdev)
2226{
2227 if (!hdev_is_powered(hdev))
2228 return false;
2229
2230 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002231 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2232 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002233 return true;
2234 }
2235
2236 return false;
2237}
2238
Johan Hedberg92da6092013-03-15 17:06:55 -05002239static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2240{
2241 BT_DBG("status 0x%02x", status);
2242
2243 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2244}
2245
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002246static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002247 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002248{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002249 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002250 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002251 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002252 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 -05002253 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002254 int err, found;
2255
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002256 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002257
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002258 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002259
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002260 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002261 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002262 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002263 goto unlock;
2264 }
2265
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002266 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002267 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002268
Johan Hedberg24b78d02012-02-23 23:24:30 +02002269 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002270 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002271 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002272 goto unlock;
2273 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002274
Johan Hedberg9246a862012-02-23 21:33:16 +02002275 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002276 }
2277
2278 found = 0;
2279
Johan Hedberg056341c2013-01-27 00:31:30 +02002280 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002281 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2282 continue;
2283
2284 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002285 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002286 found++;
2287 }
2288
2289 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002290 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002291 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002292 goto unlock;
2293 }
2294
Johan Hedberg9246a862012-02-23 21:33:16 +02002295update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002296 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002297
Johan Hedberg890ea892013-03-15 17:06:52 -05002298 update_class(&req);
2299 update_eir(&req);
2300
Johan Hedberg92da6092013-03-15 17:06:55 -05002301 err = hci_req_run(&req, remove_uuid_complete);
2302 if (err < 0) {
2303 if (err != -ENODATA)
2304 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002305
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002306 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002307 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002308 goto unlock;
2309 }
2310
2311 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002312 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002313 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002314 goto unlock;
2315 }
2316
2317 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002318
2319unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002320 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002321 return err;
2322}
2323
Johan Hedberg92da6092013-03-15 17:06:55 -05002324static void set_class_complete(struct hci_dev *hdev, u8 status)
2325{
2326 BT_DBG("status 0x%02x", status);
2327
2328 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2329}
2330
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002331static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002332 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002333{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002334 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002335 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002336 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002337 int err;
2338
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002339 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002340
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002341 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002342 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2343 MGMT_STATUS_NOT_SUPPORTED);
2344
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002345 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002346
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002347 if (pending_eir_or_class(hdev)) {
2348 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2349 MGMT_STATUS_BUSY);
2350 goto unlock;
2351 }
2352
2353 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2354 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2355 MGMT_STATUS_INVALID_PARAMS);
2356 goto unlock;
2357 }
2358
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002359 hdev->major_class = cp->major;
2360 hdev->minor_class = cp->minor;
2361
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002362 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002363 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002364 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002365 goto unlock;
2366 }
2367
Johan Hedberg890ea892013-03-15 17:06:52 -05002368 hci_req_init(&req, hdev);
2369
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002370 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002371 hci_dev_unlock(hdev);
2372 cancel_delayed_work_sync(&hdev->service_cache);
2373 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002374 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002375 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002376
Johan Hedberg890ea892013-03-15 17:06:52 -05002377 update_class(&req);
2378
Johan Hedberg92da6092013-03-15 17:06:55 -05002379 err = hci_req_run(&req, set_class_complete);
2380 if (err < 0) {
2381 if (err != -ENODATA)
2382 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002383
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002384 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002385 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002386 goto unlock;
2387 }
2388
2389 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002390 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002391 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002392 goto unlock;
2393 }
2394
2395 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002396
Johan Hedbergb5235a62012-02-21 14:32:24 +02002397unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002398 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002399 return err;
2400}
2401
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002402static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002403 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002404{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002405 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002406 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002407 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002408 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002409
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002410 BT_DBG("request for %s", hdev->name);
2411
2412 if (!lmp_bredr_capable(hdev))
2413 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2414 MGMT_STATUS_NOT_SUPPORTED);
2415
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002416 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002417
Johan Hedberg86742e12011-11-07 23:13:38 +02002418 expected_len = sizeof(*cp) + key_count *
2419 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002420 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002421 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002422 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002423 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002424 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002425 }
2426
Johan Hedberg4ae14302013-01-20 14:27:13 +02002427 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2428 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2429 MGMT_STATUS_INVALID_PARAMS);
2430
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002431 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002432 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002433
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002434 for (i = 0; i < key_count; i++) {
2435 struct mgmt_link_key_info *key = &cp->keys[i];
2436
Marcel Holtmann8e991132014-01-10 02:07:25 -08002437 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002438 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2439 MGMT_STATUS_INVALID_PARAMS);
2440 }
2441
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002442 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002443
2444 hci_link_keys_clear(hdev);
2445
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002446 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002447 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2448 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002449 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002450 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2451 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002452
2453 if (changed)
2454 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002455
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002456 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002457 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002458
Johan Hedberg58e92932014-06-24 14:00:26 +03002459 /* Always ignore debug keys and require a new pairing if
2460 * the user wants to use them.
2461 */
2462 if (key->type == HCI_LK_DEBUG_COMBINATION)
2463 continue;
2464
Johan Hedberg7652ff62014-06-24 13:15:49 +03002465 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2466 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002467 }
2468
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002469 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002470
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002471 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002472
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002473 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002474}
2475
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002476static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002477 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002478{
2479 struct mgmt_ev_device_unpaired ev;
2480
2481 bacpy(&ev.addr.bdaddr, bdaddr);
2482 ev.addr.type = addr_type;
2483
2484 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002485 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002486}
2487
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002489 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002490{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002491 struct mgmt_cp_unpair_device *cp = data;
2492 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002493 struct hci_cp_disconnect dc;
2494 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002495 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002496 int err;
2497
Johan Hedberga8a1d192011-11-10 15:54:38 +02002498 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002499 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2500 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002501
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002502 if (!bdaddr_type_is_valid(cp->addr.type))
2503 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2504 MGMT_STATUS_INVALID_PARAMS,
2505 &rp, sizeof(rp));
2506
Johan Hedberg118da702013-01-20 14:27:20 +02002507 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2508 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2509 MGMT_STATUS_INVALID_PARAMS,
2510 &rp, sizeof(rp));
2511
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002512 hci_dev_lock(hdev);
2513
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002514 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002515 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002516 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002517 goto unlock;
2518 }
2519
Johan Hedberge0b2b272014-02-18 17:14:31 +02002520 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002521 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002522 } else {
2523 u8 addr_type;
2524
2525 if (cp->addr.type == BDADDR_LE_PUBLIC)
2526 addr_type = ADDR_LE_DEV_PUBLIC;
2527 else
2528 addr_type = ADDR_LE_DEV_RANDOM;
2529
Johan Hedberga7ec7332014-02-18 17:14:35 +02002530 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2531
Andre Guedesa9b0a042014-02-26 20:21:52 -03002532 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2533
Johan Hedberge0b2b272014-02-18 17:14:31 +02002534 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2535 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002536
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002537 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002538 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002539 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002540 goto unlock;
2541 }
2542
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002543 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002544 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002545 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002546 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002547 else
2548 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002549 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002550 } else {
2551 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002552 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002553
Johan Hedberga8a1d192011-11-10 15:54:38 +02002554 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002555 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002556 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002557 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002558 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002559 }
2560
Johan Hedberg124f6e32012-02-09 13:50:12 +02002561 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002562 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002563 if (!cmd) {
2564 err = -ENOMEM;
2565 goto unlock;
2566 }
2567
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002568 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002569 dc.reason = 0x13; /* Remote User Terminated Connection */
2570 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2571 if (err < 0)
2572 mgmt_pending_remove(cmd);
2573
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002574unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002575 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002576 return err;
2577}
2578
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002579static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002580 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002581{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002582 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002583 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002584 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002585 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002586 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002587 int err;
2588
2589 BT_DBG("");
2590
Johan Hedberg06a63b12013-01-20 14:27:21 +02002591 memset(&rp, 0, sizeof(rp));
2592 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2593 rp.addr.type = cp->addr.type;
2594
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002595 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002596 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2597 MGMT_STATUS_INVALID_PARAMS,
2598 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002600 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002601
2602 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002603 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2604 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002605 goto failed;
2606 }
2607
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002608 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002609 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2610 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002611 goto failed;
2612 }
2613
Andre Guedes591f47f2012-04-24 21:02:49 -03002614 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002615 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2616 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002617 else
2618 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002619
Vishal Agarwalf9607272012-06-13 05:32:43 +05302620 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002621 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2622 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002623 goto failed;
2624 }
2625
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002626 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002627 if (!cmd) {
2628 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002629 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002630 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002631
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002632 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002633 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002634
2635 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2636 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002637 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002638
2639failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002640 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002641 return err;
2642}
2643
Andre Guedes57c14772012-04-24 21:02:50 -03002644static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002645{
2646 switch (link_type) {
2647 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002648 switch (addr_type) {
2649 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002650 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002651
Johan Hedberg48264f02011-11-09 13:58:58 +02002652 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002653 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002654 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002655 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002656
Johan Hedberg4c659c32011-11-07 23:13:39 +02002657 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002658 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002659 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002660 }
2661}
2662
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002663static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2664 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002665{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002666 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002667 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002668 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002669 int err;
2670 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002671
2672 BT_DBG("");
2673
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002674 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002675
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002676 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002677 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002678 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002679 goto unlock;
2680 }
2681
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002682 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002683 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2684 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002685 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002686 }
2687
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002688 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002689 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002690 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002691 err = -ENOMEM;
2692 goto unlock;
2693 }
2694
Johan Hedberg2784eb42011-01-21 13:56:35 +02002695 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002696 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002697 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2698 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002699 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002700 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002701 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002702 continue;
2703 i++;
2704 }
2705
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002706 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002707
Johan Hedberg4c659c32011-11-07 23:13:39 +02002708 /* Recalculate length in case of filtered SCO connections, etc */
2709 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002711 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002712 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002713
Johan Hedberga38528f2011-01-22 06:46:43 +02002714 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002715
2716unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002717 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002718 return err;
2719}
2720
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002721static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002722 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002723{
2724 struct pending_cmd *cmd;
2725 int err;
2726
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002727 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002728 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002729 if (!cmd)
2730 return -ENOMEM;
2731
Johan Hedbergd8457692012-02-17 14:24:57 +02002732 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002733 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002734 if (err < 0)
2735 mgmt_pending_remove(cmd);
2736
2737 return err;
2738}
2739
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002740static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002741 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002742{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002743 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002744 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002745 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002746 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002747 int err;
2748
2749 BT_DBG("");
2750
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002751 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002752
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002753 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002754 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002755 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002756 goto failed;
2757 }
2758
Johan Hedbergd8457692012-02-17 14:24:57 +02002759 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002760 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002761 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002762 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002763 goto failed;
2764 }
2765
2766 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002767 struct mgmt_cp_pin_code_neg_reply ncp;
2768
2769 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002770
2771 BT_ERR("PIN code is not 16 bytes long");
2772
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002773 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002774 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002775 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002776 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002777
2778 goto failed;
2779 }
2780
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002781 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002782 if (!cmd) {
2783 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002784 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002785 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002786
Johan Hedbergd8457692012-02-17 14:24:57 +02002787 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002788 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002789 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002790
2791 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2792 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002793 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002794
2795failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002796 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002797 return err;
2798}
2799
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002800static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2801 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002802{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002803 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002804
2805 BT_DBG("");
2806
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002807 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2808 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2809 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2810
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002811 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002812
2813 hdev->io_capability = cp->io_capability;
2814
2815 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002816 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002817
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002818 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002819
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002820 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2821 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002822}
2823
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002824static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002825{
2826 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002827 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002828
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002829 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002830 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2831 continue;
2832
Johan Hedberge9a416b2011-02-19 12:05:56 -03002833 if (cmd->user_data != conn)
2834 continue;
2835
2836 return cmd;
2837 }
2838
2839 return NULL;
2840}
2841
2842static void pairing_complete(struct pending_cmd *cmd, u8 status)
2843{
2844 struct mgmt_rp_pair_device rp;
2845 struct hci_conn *conn = cmd->user_data;
2846
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002847 bacpy(&rp.addr.bdaddr, &conn->dst);
2848 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002849
Johan Hedbergaee9b212012-02-18 15:07:59 +02002850 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002851 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002852
2853 /* So we don't get further callbacks for this connection */
2854 conn->connect_cfm_cb = NULL;
2855 conn->security_cfm_cb = NULL;
2856 conn->disconn_cfm_cb = NULL;
2857
David Herrmann76a68ba2013-04-06 20:28:37 +02002858 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002859
Johan Hedberga664b5b2011-02-19 12:06:02 -03002860 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002861}
2862
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002863void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2864{
2865 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2866 struct pending_cmd *cmd;
2867
2868 cmd = find_pairing(conn);
2869 if (cmd)
2870 pairing_complete(cmd, status);
2871}
2872
Johan Hedberge9a416b2011-02-19 12:05:56 -03002873static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2874{
2875 struct pending_cmd *cmd;
2876
2877 BT_DBG("status %u", status);
2878
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002879 cmd = find_pairing(conn);
2880 if (!cmd)
2881 BT_DBG("Unable to find a pending command");
2882 else
Johan Hedberge2113262012-02-18 15:20:03 +02002883 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002884}
2885
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002886static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302887{
2888 struct pending_cmd *cmd;
2889
2890 BT_DBG("status %u", status);
2891
2892 if (!status)
2893 return;
2894
2895 cmd = find_pairing(conn);
2896 if (!cmd)
2897 BT_DBG("Unable to find a pending command");
2898 else
2899 pairing_complete(cmd, mgmt_status(status));
2900}
2901
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002902static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002903 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002904{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002905 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002906 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002907 struct pending_cmd *cmd;
2908 u8 sec_level, auth_type;
2909 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002910 int err;
2911
2912 BT_DBG("");
2913
Szymon Jancf950a30e2013-01-18 12:48:07 +01002914 memset(&rp, 0, sizeof(rp));
2915 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2916 rp.addr.type = cp->addr.type;
2917
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002918 if (!bdaddr_type_is_valid(cp->addr.type))
2919 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2920 MGMT_STATUS_INVALID_PARAMS,
2921 &rp, sizeof(rp));
2922
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002923 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2924 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2925 MGMT_STATUS_INVALID_PARAMS,
2926 &rp, sizeof(rp));
2927
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002928 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002929
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002930 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002931 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2932 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002933 goto unlock;
2934 }
2935
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002936 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002937 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002938
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002939 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002940 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2941 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002942 } else {
2943 u8 addr_type;
2944
2945 /* Convert from L2CAP channel address type to HCI address type
2946 */
2947 if (cp->addr.type == BDADDR_LE_PUBLIC)
2948 addr_type = ADDR_LE_DEV_PUBLIC;
2949 else
2950 addr_type = ADDR_LE_DEV_RANDOM;
2951
Marcel Holtmann7c264b12014-06-30 12:34:40 +02002952 /* When pairing a new device, it is expected to remember
2953 * this device for future connections. Adding the connection
2954 * parameter information ahead of time allows tracking
2955 * of the slave preferred values and will speed up any
2956 * further connection establishment.
2957 *
2958 * If connection parameters already exist, then they
2959 * will be kept and this function does nothing.
2960 */
2961 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
2962
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002963 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002964 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002965 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002966
Ville Tervo30e76272011-02-22 16:10:53 -03002967 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002968 int status;
2969
2970 if (PTR_ERR(conn) == -EBUSY)
2971 status = MGMT_STATUS_BUSY;
2972 else
2973 status = MGMT_STATUS_CONNECT_FAILED;
2974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002975 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002976 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002977 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002978 goto unlock;
2979 }
2980
2981 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002982 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002983 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002985 goto unlock;
2986 }
2987
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002988 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002989 if (!cmd) {
2990 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002991 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002992 goto unlock;
2993 }
2994
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002995 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002996 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002997 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002998 conn->security_cfm_cb = pairing_complete_cb;
2999 conn->disconn_cfm_cb = pairing_complete_cb;
3000 } else {
3001 conn->connect_cfm_cb = le_pairing_complete_cb;
3002 conn->security_cfm_cb = le_pairing_complete_cb;
3003 conn->disconn_cfm_cb = le_pairing_complete_cb;
3004 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003005
Johan Hedberge9a416b2011-02-19 12:05:56 -03003006 conn->io_capability = cp->io_cap;
3007 cmd->user_data = conn;
3008
3009 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003010 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003011 pairing_complete(cmd, 0);
3012
3013 err = 0;
3014
3015unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003016 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003017 return err;
3018}
3019
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003020static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3021 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003022{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003023 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003024 struct pending_cmd *cmd;
3025 struct hci_conn *conn;
3026 int err;
3027
3028 BT_DBG("");
3029
Johan Hedberg28424702012-02-02 04:02:29 +02003030 hci_dev_lock(hdev);
3031
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003032 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003033 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003034 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003035 goto unlock;
3036 }
3037
Johan Hedberg28424702012-02-02 04:02:29 +02003038 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3039 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003040 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003041 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003042 goto unlock;
3043 }
3044
3045 conn = cmd->user_data;
3046
3047 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003048 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003049 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003050 goto unlock;
3051 }
3052
3053 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3054
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003055 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003056 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003057unlock:
3058 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003059 return err;
3060}
3061
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003062static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003063 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003064 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003065{
Johan Hedberga5c29682011-02-19 12:05:57 -03003066 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003067 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003068 int err;
3069
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003070 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003071
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003072 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003073 err = cmd_complete(sk, hdev->id, mgmt_op,
3074 MGMT_STATUS_NOT_POWERED, addr,
3075 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003076 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003077 }
3078
Johan Hedberg1707c602013-03-15 17:07:15 -05003079 if (addr->type == BDADDR_BREDR)
3080 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003081 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003082 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003083
Johan Hedberg272d90d2012-02-09 15:26:12 +02003084 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003085 err = cmd_complete(sk, hdev->id, mgmt_op,
3086 MGMT_STATUS_NOT_CONNECTED, addr,
3087 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003088 goto done;
3089 }
3090
Johan Hedberg1707c602013-03-15 17:07:15 -05003091 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003092 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003093 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003094 err = cmd_complete(sk, hdev->id, mgmt_op,
3095 MGMT_STATUS_SUCCESS, addr,
3096 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003097 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003098 err = cmd_complete(sk, hdev->id, mgmt_op,
3099 MGMT_STATUS_FAILED, addr,
3100 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003101
Brian Gix47c15e22011-11-16 13:53:14 -08003102 goto done;
3103 }
3104
Johan Hedberg1707c602013-03-15 17:07:15 -05003105 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003106 if (!cmd) {
3107 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003108 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003109 }
3110
Brian Gix0df4c182011-11-16 13:53:13 -08003111 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003112 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3113 struct hci_cp_user_passkey_reply cp;
3114
Johan Hedberg1707c602013-03-15 17:07:15 -05003115 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003116 cp.passkey = passkey;
3117 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3118 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003119 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3120 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003121
Johan Hedberga664b5b2011-02-19 12:06:02 -03003122 if (err < 0)
3123 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003124
Brian Gix0df4c182011-11-16 13:53:13 -08003125done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003126 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003127 return err;
3128}
3129
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303130static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3131 void *data, u16 len)
3132{
3133 struct mgmt_cp_pin_code_neg_reply *cp = data;
3134
3135 BT_DBG("");
3136
Johan Hedberg1707c602013-03-15 17:07:15 -05003137 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303138 MGMT_OP_PIN_CODE_NEG_REPLY,
3139 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3140}
3141
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003142static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3143 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003144{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003145 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003146
3147 BT_DBG("");
3148
3149 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003150 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003151 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003152
Johan Hedberg1707c602013-03-15 17:07:15 -05003153 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003154 MGMT_OP_USER_CONFIRM_REPLY,
3155 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003156}
3157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003158static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003159 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003160{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003161 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003162
3163 BT_DBG("");
3164
Johan Hedberg1707c602013-03-15 17:07:15 -05003165 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003166 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3167 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003168}
3169
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3171 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003172{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003173 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003174
3175 BT_DBG("");
3176
Johan Hedberg1707c602013-03-15 17:07:15 -05003177 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003178 MGMT_OP_USER_PASSKEY_REPLY,
3179 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003180}
3181
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003182static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003183 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003184{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003185 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003186
3187 BT_DBG("");
3188
Johan Hedberg1707c602013-03-15 17:07:15 -05003189 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003190 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3191 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003192}
3193
Johan Hedberg13928972013-03-15 17:07:00 -05003194static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003195{
Johan Hedberg13928972013-03-15 17:07:00 -05003196 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003197 struct hci_cp_write_local_name cp;
3198
Johan Hedberg13928972013-03-15 17:07:00 -05003199 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003200
Johan Hedberg890ea892013-03-15 17:06:52 -05003201 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003202}
3203
Johan Hedberg13928972013-03-15 17:07:00 -05003204static void set_name_complete(struct hci_dev *hdev, u8 status)
3205{
3206 struct mgmt_cp_set_local_name *cp;
3207 struct pending_cmd *cmd;
3208
3209 BT_DBG("status 0x%02x", status);
3210
3211 hci_dev_lock(hdev);
3212
3213 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3214 if (!cmd)
3215 goto unlock;
3216
3217 cp = cmd->param;
3218
3219 if (status)
3220 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3221 mgmt_status(status));
3222 else
3223 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3224 cp, sizeof(*cp));
3225
3226 mgmt_pending_remove(cmd);
3227
3228unlock:
3229 hci_dev_unlock(hdev);
3230}
3231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003232static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003233 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003234{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003235 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003236 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003237 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003238 int err;
3239
3240 BT_DBG("");
3241
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003242 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003243
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003244 /* If the old values are the same as the new ones just return a
3245 * direct command complete event.
3246 */
3247 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3248 !memcmp(hdev->short_name, cp->short_name,
3249 sizeof(hdev->short_name))) {
3250 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3251 data, len);
3252 goto failed;
3253 }
3254
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003255 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003256
Johan Hedbergb5235a62012-02-21 14:32:24 +02003257 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003258 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003259
3260 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003261 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003262 if (err < 0)
3263 goto failed;
3264
3265 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003266 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003267
Johan Hedbergb5235a62012-02-21 14:32:24 +02003268 goto failed;
3269 }
3270
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003271 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003272 if (!cmd) {
3273 err = -ENOMEM;
3274 goto failed;
3275 }
3276
Johan Hedberg13928972013-03-15 17:07:00 -05003277 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3278
Johan Hedberg890ea892013-03-15 17:06:52 -05003279 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003280
3281 if (lmp_bredr_capable(hdev)) {
3282 update_name(&req);
3283 update_eir(&req);
3284 }
3285
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003286 /* The name is stored in the scan response data and so
3287 * no need to udpate the advertising data here.
3288 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003289 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003290 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003291
Johan Hedberg13928972013-03-15 17:07:00 -05003292 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003293 if (err < 0)
3294 mgmt_pending_remove(cmd);
3295
3296failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003297 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003298 return err;
3299}
3300
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003301static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003303{
Szymon Jancc35938b2011-03-22 13:12:21 +01003304 struct pending_cmd *cmd;
3305 int err;
3306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003307 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003308
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003309 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003310
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003311 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003312 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003313 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003314 goto unlock;
3315 }
3316
Andre Guedes9a1a1992012-07-24 15:03:48 -03003317 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003318 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003319 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003320 goto unlock;
3321 }
3322
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003323 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003324 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003325 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003326 goto unlock;
3327 }
3328
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003329 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003330 if (!cmd) {
3331 err = -ENOMEM;
3332 goto unlock;
3333 }
3334
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003335 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3336 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3337 0, NULL);
3338 else
3339 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3340
Szymon Jancc35938b2011-03-22 13:12:21 +01003341 if (err < 0)
3342 mgmt_pending_remove(cmd);
3343
3344unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003345 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003346 return err;
3347}
3348
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003349static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003350 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003351{
Szymon Janc2763eda2011-03-22 13:12:22 +01003352 int err;
3353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003354 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003355
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003356 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003357
Marcel Holtmannec109112014-01-10 02:07:30 -08003358 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3359 struct mgmt_cp_add_remote_oob_data *cp = data;
3360 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003361
Marcel Holtmannec109112014-01-10 02:07:30 -08003362 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3363 cp->hash, cp->randomizer);
3364 if (err < 0)
3365 status = MGMT_STATUS_FAILED;
3366 else
3367 status = MGMT_STATUS_SUCCESS;
3368
3369 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3370 status, &cp->addr, sizeof(cp->addr));
3371 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3372 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3373 u8 status;
3374
3375 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3376 cp->hash192,
3377 cp->randomizer192,
3378 cp->hash256,
3379 cp->randomizer256);
3380 if (err < 0)
3381 status = MGMT_STATUS_FAILED;
3382 else
3383 status = MGMT_STATUS_SUCCESS;
3384
3385 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3386 status, &cp->addr, sizeof(cp->addr));
3387 } else {
3388 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3389 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3390 MGMT_STATUS_INVALID_PARAMS);
3391 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003392
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003393 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003394 return err;
3395}
3396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003397static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003398 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003399{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003400 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003401 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003402 int err;
3403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003404 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003405
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003406 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003407
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003408 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003409 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003410 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003411 else
Szymon Janca6785be2012-12-13 15:11:21 +01003412 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003414 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003415 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003416
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003417 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003418 return err;
3419}
3420
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003421static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3422{
3423 struct pending_cmd *cmd;
3424 u8 type;
3425 int err;
3426
3427 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3428
3429 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3430 if (!cmd)
3431 return -ENOENT;
3432
3433 type = hdev->discovery.type;
3434
3435 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3436 &type, sizeof(type));
3437 mgmt_pending_remove(cmd);
3438
3439 return err;
3440}
3441
Andre Guedes7c307722013-04-30 15:29:28 -03003442static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3443{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003444 unsigned long timeout = 0;
3445
Andre Guedes7c307722013-04-30 15:29:28 -03003446 BT_DBG("status %d", status);
3447
3448 if (status) {
3449 hci_dev_lock(hdev);
3450 mgmt_start_discovery_failed(hdev, status);
3451 hci_dev_unlock(hdev);
3452 return;
3453 }
3454
3455 hci_dev_lock(hdev);
3456 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3457 hci_dev_unlock(hdev);
3458
3459 switch (hdev->discovery.type) {
3460 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003461 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003462 break;
3463
3464 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003465 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003466 break;
3467
3468 case DISCOV_TYPE_BREDR:
3469 break;
3470
3471 default:
3472 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3473 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003474
3475 if (!timeout)
3476 return;
3477
3478 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003479}
3480
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003481static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003482 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003483{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003484 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003485 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003486 struct hci_cp_le_set_scan_param param_cp;
3487 struct hci_cp_le_set_scan_enable enable_cp;
3488 struct hci_cp_inquiry inq_cp;
3489 struct hci_request req;
3490 /* General inquiry access code (GIAC) */
3491 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003492 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003493 int err;
3494
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003495 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003496
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003497 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003498
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003499 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003500 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003501 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003502 goto failed;
3503 }
3504
Andre Guedes642be6c2012-03-21 00:03:37 -03003505 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3506 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3507 MGMT_STATUS_BUSY);
3508 goto failed;
3509 }
3510
Johan Hedbergff9ef572012-01-04 14:23:45 +02003511 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003512 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003513 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003514 goto failed;
3515 }
3516
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003517 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003518 if (!cmd) {
3519 err = -ENOMEM;
3520 goto failed;
3521 }
3522
Andre Guedes4aab14e2012-02-17 20:39:36 -03003523 hdev->discovery.type = cp->type;
3524
Andre Guedes7c307722013-04-30 15:29:28 -03003525 hci_req_init(&req, hdev);
3526
Andre Guedes4aab14e2012-02-17 20:39:36 -03003527 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003528 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003529 status = mgmt_bredr_support(hdev);
3530 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003531 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003532 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003533 mgmt_pending_remove(cmd);
3534 goto failed;
3535 }
3536
Andre Guedes7c307722013-04-30 15:29:28 -03003537 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3538 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3539 MGMT_STATUS_BUSY);
3540 mgmt_pending_remove(cmd);
3541 goto failed;
3542 }
3543
3544 hci_inquiry_cache_flush(hdev);
3545
3546 memset(&inq_cp, 0, sizeof(inq_cp));
3547 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003548 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003549 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003550 break;
3551
3552 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003553 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003554 status = mgmt_le_support(hdev);
3555 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003556 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003557 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003558 mgmt_pending_remove(cmd);
3559 goto failed;
3560 }
3561
Andre Guedes7c307722013-04-30 15:29:28 -03003562 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003563 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003564 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3565 MGMT_STATUS_NOT_SUPPORTED);
3566 mgmt_pending_remove(cmd);
3567 goto failed;
3568 }
3569
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003570 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003571 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3572 MGMT_STATUS_REJECTED);
3573 mgmt_pending_remove(cmd);
3574 goto failed;
3575 }
3576
Andre Guedesc54c3862014-02-26 20:21:50 -03003577 /* If controller is scanning, it means the background scanning
3578 * is running. Thus, we should temporarily stop it in order to
3579 * set the discovery scanning parameters.
3580 */
3581 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3582 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003583
3584 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003585
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003586 /* All active scans will be done with either a resolvable
3587 * private address (when privacy feature has been enabled)
3588 * or unresolvable private address.
3589 */
3590 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003591 if (err < 0) {
3592 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3593 MGMT_STATUS_FAILED);
3594 mgmt_pending_remove(cmd);
3595 goto failed;
3596 }
3597
Andre Guedes7c307722013-04-30 15:29:28 -03003598 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003599 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3600 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003601 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003602 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3603 &param_cp);
3604
3605 memset(&enable_cp, 0, sizeof(enable_cp));
3606 enable_cp.enable = LE_SCAN_ENABLE;
3607 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3608 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3609 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003610 break;
3611
Andre Guedesf39799f2012-02-17 20:39:35 -03003612 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003613 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3614 MGMT_STATUS_INVALID_PARAMS);
3615 mgmt_pending_remove(cmd);
3616 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003617 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003618
Andre Guedes7c307722013-04-30 15:29:28 -03003619 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003620 if (err < 0)
3621 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003622 else
3623 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003624
3625failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003626 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003627 return err;
3628}
3629
Andre Guedes1183fdc2013-04-30 15:29:35 -03003630static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3631{
3632 struct pending_cmd *cmd;
3633 int err;
3634
3635 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3636 if (!cmd)
3637 return -ENOENT;
3638
3639 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3640 &hdev->discovery.type, sizeof(hdev->discovery.type));
3641 mgmt_pending_remove(cmd);
3642
3643 return err;
3644}
3645
Andre Guedes0e05bba2013-04-30 15:29:33 -03003646static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3647{
3648 BT_DBG("status %d", status);
3649
3650 hci_dev_lock(hdev);
3651
3652 if (status) {
3653 mgmt_stop_discovery_failed(hdev, status);
3654 goto unlock;
3655 }
3656
3657 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3658
3659unlock:
3660 hci_dev_unlock(hdev);
3661}
3662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003663static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003665{
Johan Hedbergd9306502012-02-20 23:25:18 +02003666 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003667 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003668 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003669 int err;
3670
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003671 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003673 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003674
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003675 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003676 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003677 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3678 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003679 goto unlock;
3680 }
3681
3682 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003683 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003684 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3685 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003686 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003687 }
3688
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003689 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003690 if (!cmd) {
3691 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003692 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003693 }
3694
Andre Guedes0e05bba2013-04-30 15:29:33 -03003695 hci_req_init(&req, hdev);
3696
Johan Hedberg21a60d32014-06-10 14:05:58 +03003697 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003698
Johan Hedberg21a60d32014-06-10 14:05:58 +03003699 err = hci_req_run(&req, stop_discovery_complete);
3700 if (!err) {
3701 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003702 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003703 }
3704
Johan Hedberg21a60d32014-06-10 14:05:58 +03003705 mgmt_pending_remove(cmd);
3706
3707 /* If no HCI commands were sent we're done */
3708 if (err == -ENODATA) {
3709 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3710 &mgmt_cp->type, sizeof(mgmt_cp->type));
3711 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3712 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003713
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003714unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003715 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003716 return err;
3717}
3718
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003719static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003720 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003721{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003722 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003723 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003724 int err;
3725
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003726 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003727
Johan Hedberg561aafb2012-01-04 13:31:59 +02003728 hci_dev_lock(hdev);
3729
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003730 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003731 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3732 MGMT_STATUS_FAILED, &cp->addr,
3733 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003734 goto failed;
3735 }
3736
Johan Hedberga198e7b2012-02-17 14:27:06 +02003737 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003738 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003739 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3740 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3741 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003742 goto failed;
3743 }
3744
3745 if (cp->name_known) {
3746 e->name_state = NAME_KNOWN;
3747 list_del(&e->list);
3748 } else {
3749 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003750 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003751 }
3752
Johan Hedberge3846622013-01-09 15:29:33 +02003753 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3754 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003755
3756failed:
3757 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003758 return err;
3759}
3760
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003761static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003762 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003763{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003764 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003765 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003766 int err;
3767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003768 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003769
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003770 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003771 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3772 MGMT_STATUS_INVALID_PARAMS,
3773 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003774
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003775 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003776
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003777 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003778 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003779 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003780 goto done;
3781 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003782
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003783 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3784 sk);
3785 status = MGMT_STATUS_SUCCESS;
3786
3787done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003788 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003789 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003790
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003791 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003792
3793 return err;
3794}
3795
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003796static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003797 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003798{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003799 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003800 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003801 int err;
3802
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003803 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003804
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003805 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003806 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3807 MGMT_STATUS_INVALID_PARAMS,
3808 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003809
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003810 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003811
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003812 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003813 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003814 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003815 goto done;
3816 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003817
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003818 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3819 sk);
3820 status = MGMT_STATUS_SUCCESS;
3821
3822done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003823 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003824 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003825
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003826 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003827
3828 return err;
3829}
3830
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003831static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3832 u16 len)
3833{
3834 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003835 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003836 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003837 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003838
3839 BT_DBG("%s", hdev->name);
3840
Szymon Jancc72d4b82012-03-16 16:02:57 +01003841 source = __le16_to_cpu(cp->source);
3842
3843 if (source > 0x0002)
3844 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3845 MGMT_STATUS_INVALID_PARAMS);
3846
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003847 hci_dev_lock(hdev);
3848
Szymon Jancc72d4b82012-03-16 16:02:57 +01003849 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003850 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3851 hdev->devid_product = __le16_to_cpu(cp->product);
3852 hdev->devid_version = __le16_to_cpu(cp->version);
3853
3854 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3855
Johan Hedberg890ea892013-03-15 17:06:52 -05003856 hci_req_init(&req, hdev);
3857 update_eir(&req);
3858 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003859
3860 hci_dev_unlock(hdev);
3861
3862 return err;
3863}
3864
Johan Hedberg4375f102013-09-25 13:26:10 +03003865static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3866{
3867 struct cmd_lookup match = { NULL, hdev };
3868
3869 if (status) {
3870 u8 mgmt_err = mgmt_status(status);
3871
3872 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3873 cmd_status_rsp, &mgmt_err);
3874 return;
3875 }
3876
3877 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3878 &match);
3879
3880 new_settings(hdev, match.sk);
3881
3882 if (match.sk)
3883 sock_put(match.sk);
3884}
3885
Marcel Holtmann21b51872013-10-10 09:47:53 -07003886static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3887 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003888{
3889 struct mgmt_mode *cp = data;
3890 struct pending_cmd *cmd;
3891 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003892 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003893 int err;
3894
3895 BT_DBG("request for %s", hdev->name);
3896
Johan Hedberge6fe7982013-10-02 15:45:22 +03003897 status = mgmt_le_support(hdev);
3898 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003899 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003900 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003901
3902 if (cp->val != 0x00 && cp->val != 0x01)
3903 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3904 MGMT_STATUS_INVALID_PARAMS);
3905
3906 hci_dev_lock(hdev);
3907
3908 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003909 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003910
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003911 /* The following conditions are ones which mean that we should
3912 * not do any HCI communication but directly send a mgmt
3913 * response to user space (after toggling the flag if
3914 * necessary).
3915 */
3916 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003917 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003918 bool changed = false;
3919
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003920 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3921 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003922 changed = true;
3923 }
3924
3925 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3926 if (err < 0)
3927 goto unlock;
3928
3929 if (changed)
3930 err = new_settings(hdev, sk);
3931
3932 goto unlock;
3933 }
3934
3935 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3936 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3937 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3938 MGMT_STATUS_BUSY);
3939 goto unlock;
3940 }
3941
3942 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3943 if (!cmd) {
3944 err = -ENOMEM;
3945 goto unlock;
3946 }
3947
3948 hci_req_init(&req, hdev);
3949
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003950 if (val)
3951 enable_advertising(&req);
3952 else
3953 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003954
3955 err = hci_req_run(&req, set_advertising_complete);
3956 if (err < 0)
3957 mgmt_pending_remove(cmd);
3958
3959unlock:
3960 hci_dev_unlock(hdev);
3961 return err;
3962}
3963
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003964static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3965 void *data, u16 len)
3966{
3967 struct mgmt_cp_set_static_address *cp = data;
3968 int err;
3969
3970 BT_DBG("%s", hdev->name);
3971
Marcel Holtmann62af4442013-10-02 22:10:32 -07003972 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003973 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003974 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003975
3976 if (hdev_is_powered(hdev))
3977 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3978 MGMT_STATUS_REJECTED);
3979
3980 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3981 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3982 return cmd_status(sk, hdev->id,
3983 MGMT_OP_SET_STATIC_ADDRESS,
3984 MGMT_STATUS_INVALID_PARAMS);
3985
3986 /* Two most significant bits shall be set */
3987 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3988 return cmd_status(sk, hdev->id,
3989 MGMT_OP_SET_STATIC_ADDRESS,
3990 MGMT_STATUS_INVALID_PARAMS);
3991 }
3992
3993 hci_dev_lock(hdev);
3994
3995 bacpy(&hdev->static_addr, &cp->bdaddr);
3996
3997 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3998
3999 hci_dev_unlock(hdev);
4000
4001 return err;
4002}
4003
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004004static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4005 void *data, u16 len)
4006{
4007 struct mgmt_cp_set_scan_params *cp = data;
4008 __u16 interval, window;
4009 int err;
4010
4011 BT_DBG("%s", hdev->name);
4012
4013 if (!lmp_le_capable(hdev))
4014 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4015 MGMT_STATUS_NOT_SUPPORTED);
4016
4017 interval = __le16_to_cpu(cp->interval);
4018
4019 if (interval < 0x0004 || interval > 0x4000)
4020 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4021 MGMT_STATUS_INVALID_PARAMS);
4022
4023 window = __le16_to_cpu(cp->window);
4024
4025 if (window < 0x0004 || window > 0x4000)
4026 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4027 MGMT_STATUS_INVALID_PARAMS);
4028
Marcel Holtmann899e1072013-10-14 09:55:32 -07004029 if (window > interval)
4030 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4031 MGMT_STATUS_INVALID_PARAMS);
4032
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004033 hci_dev_lock(hdev);
4034
4035 hdev->le_scan_interval = interval;
4036 hdev->le_scan_window = window;
4037
4038 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4039
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004040 /* If background scan is running, restart it so new parameters are
4041 * loaded.
4042 */
4043 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4044 hdev->discovery.state == DISCOVERY_STOPPED) {
4045 struct hci_request req;
4046
4047 hci_req_init(&req, hdev);
4048
4049 hci_req_add_le_scan_disable(&req);
4050 hci_req_add_le_passive_scan(&req);
4051
4052 hci_req_run(&req, NULL);
4053 }
4054
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004055 hci_dev_unlock(hdev);
4056
4057 return err;
4058}
4059
Johan Hedberg33e38b32013-03-15 17:07:05 -05004060static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4061{
4062 struct pending_cmd *cmd;
4063
4064 BT_DBG("status 0x%02x", status);
4065
4066 hci_dev_lock(hdev);
4067
4068 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4069 if (!cmd)
4070 goto unlock;
4071
4072 if (status) {
4073 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4074 mgmt_status(status));
4075 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004076 struct mgmt_mode *cp = cmd->param;
4077
4078 if (cp->val)
4079 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4080 else
4081 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4082
Johan Hedberg33e38b32013-03-15 17:07:05 -05004083 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4084 new_settings(hdev, cmd->sk);
4085 }
4086
4087 mgmt_pending_remove(cmd);
4088
4089unlock:
4090 hci_dev_unlock(hdev);
4091}
4092
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004093static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004094 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004095{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004096 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004097 struct pending_cmd *cmd;
4098 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004099 int err;
4100
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004101 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004102
Johan Hedberg56f87902013-10-02 13:43:13 +03004103 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4104 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004105 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4106 MGMT_STATUS_NOT_SUPPORTED);
4107
Johan Hedberga7e80f22013-01-09 16:05:19 +02004108 if (cp->val != 0x00 && cp->val != 0x01)
4109 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4110 MGMT_STATUS_INVALID_PARAMS);
4111
Johan Hedberg5400c042012-02-21 16:40:33 +02004112 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004113 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004114 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004115
4116 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004117 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004118 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004119
4120 hci_dev_lock(hdev);
4121
Johan Hedberg05cbf292013-03-15 17:07:07 -05004122 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4123 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4124 MGMT_STATUS_BUSY);
4125 goto unlock;
4126 }
4127
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004128 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4129 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4130 hdev);
4131 goto unlock;
4132 }
4133
Johan Hedberg33e38b32013-03-15 17:07:05 -05004134 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4135 data, len);
4136 if (!cmd) {
4137 err = -ENOMEM;
4138 goto unlock;
4139 }
4140
4141 hci_req_init(&req, hdev);
4142
Johan Hedberg406d7802013-03-15 17:07:09 -05004143 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004144
4145 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004146 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004147 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004148 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004149 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004150 }
4151
Johan Hedberg33e38b32013-03-15 17:07:05 -05004152unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004153 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004154
Antti Julkuf6422ec2011-06-22 13:11:56 +03004155 return err;
4156}
4157
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004158static void set_bredr_scan(struct hci_request *req)
4159{
4160 struct hci_dev *hdev = req->hdev;
4161 u8 scan = 0;
4162
4163 /* Ensure that fast connectable is disabled. This function will
4164 * not do anything if the page scan parameters are already what
4165 * they should be.
4166 */
4167 write_fast_connectable(req, false);
4168
4169 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4170 scan |= SCAN_PAGE;
4171 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4172 scan |= SCAN_INQUIRY;
4173
4174 if (scan)
4175 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4176}
4177
Johan Hedberg0663ca22013-10-02 13:43:14 +03004178static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4179{
4180 struct pending_cmd *cmd;
4181
4182 BT_DBG("status 0x%02x", status);
4183
4184 hci_dev_lock(hdev);
4185
4186 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4187 if (!cmd)
4188 goto unlock;
4189
4190 if (status) {
4191 u8 mgmt_err = mgmt_status(status);
4192
4193 /* We need to restore the flag if related HCI commands
4194 * failed.
4195 */
4196 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4197
4198 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4199 } else {
4200 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4201 new_settings(hdev, cmd->sk);
4202 }
4203
4204 mgmt_pending_remove(cmd);
4205
4206unlock:
4207 hci_dev_unlock(hdev);
4208}
4209
4210static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4211{
4212 struct mgmt_mode *cp = data;
4213 struct pending_cmd *cmd;
4214 struct hci_request req;
4215 int err;
4216
4217 BT_DBG("request for %s", hdev->name);
4218
4219 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4220 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4221 MGMT_STATUS_NOT_SUPPORTED);
4222
4223 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4224 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4225 MGMT_STATUS_REJECTED);
4226
4227 if (cp->val != 0x00 && cp->val != 0x01)
4228 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4229 MGMT_STATUS_INVALID_PARAMS);
4230
4231 hci_dev_lock(hdev);
4232
4233 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4234 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4235 goto unlock;
4236 }
4237
4238 if (!hdev_is_powered(hdev)) {
4239 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004240 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4241 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4242 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4243 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4244 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4245 }
4246
4247 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4248
4249 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4250 if (err < 0)
4251 goto unlock;
4252
4253 err = new_settings(hdev, sk);
4254 goto unlock;
4255 }
4256
4257 /* Reject disabling when powered on */
4258 if (!cp->val) {
4259 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4260 MGMT_STATUS_REJECTED);
4261 goto unlock;
4262 }
4263
4264 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4265 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4266 MGMT_STATUS_BUSY);
4267 goto unlock;
4268 }
4269
4270 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4271 if (!cmd) {
4272 err = -ENOMEM;
4273 goto unlock;
4274 }
4275
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004276 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004277 * generates the correct flags.
4278 */
4279 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4280
4281 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004282
4283 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4284 set_bredr_scan(&req);
4285
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004286 /* Since only the advertising data flags will change, there
4287 * is no need to update the scan response data.
4288 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004289 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004290
Johan Hedberg0663ca22013-10-02 13:43:14 +03004291 err = hci_req_run(&req, set_bredr_complete);
4292 if (err < 0)
4293 mgmt_pending_remove(cmd);
4294
4295unlock:
4296 hci_dev_unlock(hdev);
4297 return err;
4298}
4299
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004300static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4301 void *data, u16 len)
4302{
4303 struct mgmt_mode *cp = data;
4304 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004305 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004306 int err;
4307
4308 BT_DBG("request for %s", hdev->name);
4309
4310 status = mgmt_bredr_support(hdev);
4311 if (status)
4312 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4313 status);
4314
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004315 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004316 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004317 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4318 MGMT_STATUS_NOT_SUPPORTED);
4319
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004320 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004321 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4322 MGMT_STATUS_INVALID_PARAMS);
4323
4324 hci_dev_lock(hdev);
4325
4326 if (!hdev_is_powered(hdev)) {
4327 bool changed;
4328
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004329 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004330 changed = !test_and_set_bit(HCI_SC_ENABLED,
4331 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004332 if (cp->val == 0x02)
4333 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4334 else
4335 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4336 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004337 changed = test_and_clear_bit(HCI_SC_ENABLED,
4338 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004339 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4340 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004341
4342 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4343 if (err < 0)
4344 goto failed;
4345
4346 if (changed)
4347 err = new_settings(hdev, sk);
4348
4349 goto failed;
4350 }
4351
4352 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4353 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4354 MGMT_STATUS_BUSY);
4355 goto failed;
4356 }
4357
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004358 val = !!cp->val;
4359
4360 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4361 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004362 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4363 goto failed;
4364 }
4365
4366 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4367 if (!cmd) {
4368 err = -ENOMEM;
4369 goto failed;
4370 }
4371
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004372 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004373 if (err < 0) {
4374 mgmt_pending_remove(cmd);
4375 goto failed;
4376 }
4377
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004378 if (cp->val == 0x02)
4379 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4380 else
4381 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4382
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004383failed:
4384 hci_dev_unlock(hdev);
4385 return err;
4386}
4387
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004388static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4389 void *data, u16 len)
4390{
4391 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004392 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004393 int err;
4394
4395 BT_DBG("request for %s", hdev->name);
4396
Johan Hedbergb97109792014-06-24 14:00:28 +03004397 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004398 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4399 MGMT_STATUS_INVALID_PARAMS);
4400
4401 hci_dev_lock(hdev);
4402
4403 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004404 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4405 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004406 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004407 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4408 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004409
Johan Hedbergb97109792014-06-24 14:00:28 +03004410 if (cp->val == 0x02)
4411 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4412 &hdev->dev_flags);
4413 else
4414 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4415 &hdev->dev_flags);
4416
4417 if (hdev_is_powered(hdev) && use_changed &&
4418 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4419 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4420 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4421 sizeof(mode), &mode);
4422 }
4423
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004424 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4425 if (err < 0)
4426 goto unlock;
4427
4428 if (changed)
4429 err = new_settings(hdev, sk);
4430
4431unlock:
4432 hci_dev_unlock(hdev);
4433 return err;
4434}
4435
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004436static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4437 u16 len)
4438{
4439 struct mgmt_cp_set_privacy *cp = cp_data;
4440 bool changed;
4441 int err;
4442
4443 BT_DBG("request for %s", hdev->name);
4444
4445 if (!lmp_le_capable(hdev))
4446 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4447 MGMT_STATUS_NOT_SUPPORTED);
4448
4449 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4450 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4451 MGMT_STATUS_INVALID_PARAMS);
4452
4453 if (hdev_is_powered(hdev))
4454 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4455 MGMT_STATUS_REJECTED);
4456
4457 hci_dev_lock(hdev);
4458
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004459 /* If user space supports this command it is also expected to
4460 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4461 */
4462 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4463
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004464 if (cp->privacy) {
4465 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4466 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4467 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4468 } else {
4469 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4470 memset(hdev->irk, 0, sizeof(hdev->irk));
4471 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4472 }
4473
4474 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4475 if (err < 0)
4476 goto unlock;
4477
4478 if (changed)
4479 err = new_settings(hdev, sk);
4480
4481unlock:
4482 hci_dev_unlock(hdev);
4483 return err;
4484}
4485
Johan Hedberg41edf162014-02-18 10:19:35 +02004486static bool irk_is_valid(struct mgmt_irk_info *irk)
4487{
4488 switch (irk->addr.type) {
4489 case BDADDR_LE_PUBLIC:
4490 return true;
4491
4492 case BDADDR_LE_RANDOM:
4493 /* Two most significant bits shall be set */
4494 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4495 return false;
4496 return true;
4497 }
4498
4499 return false;
4500}
4501
4502static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4503 u16 len)
4504{
4505 struct mgmt_cp_load_irks *cp = cp_data;
4506 u16 irk_count, expected_len;
4507 int i, err;
4508
4509 BT_DBG("request for %s", hdev->name);
4510
4511 if (!lmp_le_capable(hdev))
4512 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4513 MGMT_STATUS_NOT_SUPPORTED);
4514
4515 irk_count = __le16_to_cpu(cp->irk_count);
4516
4517 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4518 if (expected_len != len) {
4519 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004520 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004521 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4522 MGMT_STATUS_INVALID_PARAMS);
4523 }
4524
4525 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4526
4527 for (i = 0; i < irk_count; i++) {
4528 struct mgmt_irk_info *key = &cp->irks[i];
4529
4530 if (!irk_is_valid(key))
4531 return cmd_status(sk, hdev->id,
4532 MGMT_OP_LOAD_IRKS,
4533 MGMT_STATUS_INVALID_PARAMS);
4534 }
4535
4536 hci_dev_lock(hdev);
4537
4538 hci_smp_irks_clear(hdev);
4539
4540 for (i = 0; i < irk_count; i++) {
4541 struct mgmt_irk_info *irk = &cp->irks[i];
4542 u8 addr_type;
4543
4544 if (irk->addr.type == BDADDR_LE_PUBLIC)
4545 addr_type = ADDR_LE_DEV_PUBLIC;
4546 else
4547 addr_type = ADDR_LE_DEV_RANDOM;
4548
4549 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4550 BDADDR_ANY);
4551 }
4552
4553 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4554
4555 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4556
4557 hci_dev_unlock(hdev);
4558
4559 return err;
4560}
4561
Johan Hedberg3f706b72013-01-20 14:27:16 +02004562static bool ltk_is_valid(struct mgmt_ltk_info *key)
4563{
4564 if (key->master != 0x00 && key->master != 0x01)
4565 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004566
4567 switch (key->addr.type) {
4568 case BDADDR_LE_PUBLIC:
4569 return true;
4570
4571 case BDADDR_LE_RANDOM:
4572 /* Two most significant bits shall be set */
4573 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4574 return false;
4575 return true;
4576 }
4577
4578 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004579}
4580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004581static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004582 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004583{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004584 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4585 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004586 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004587
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004588 BT_DBG("request for %s", hdev->name);
4589
4590 if (!lmp_le_capable(hdev))
4591 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4592 MGMT_STATUS_NOT_SUPPORTED);
4593
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004594 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004595
4596 expected_len = sizeof(*cp) + key_count *
4597 sizeof(struct mgmt_ltk_info);
4598 if (expected_len != len) {
4599 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004600 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004601 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004602 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004603 }
4604
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004605 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004606
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004607 for (i = 0; i < key_count; i++) {
4608 struct mgmt_ltk_info *key = &cp->keys[i];
4609
Johan Hedberg3f706b72013-01-20 14:27:16 +02004610 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004611 return cmd_status(sk, hdev->id,
4612 MGMT_OP_LOAD_LONG_TERM_KEYS,
4613 MGMT_STATUS_INVALID_PARAMS);
4614 }
4615
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004616 hci_dev_lock(hdev);
4617
4618 hci_smp_ltks_clear(hdev);
4619
4620 for (i = 0; i < key_count; i++) {
4621 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004622 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004623
4624 if (key->addr.type == BDADDR_LE_PUBLIC)
4625 addr_type = ADDR_LE_DEV_PUBLIC;
4626 else
4627 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004628
4629 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004630 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004631 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004632 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004633
Johan Hedberg61b43352014-05-29 19:36:53 +03004634 switch (key->type) {
4635 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004636 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004637 break;
4638 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004639 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004640 break;
4641 default:
4642 continue;
4643 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004644
Johan Hedberg35d70272014-02-19 14:57:47 +02004645 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004646 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004647 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004648 }
4649
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004650 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4651 NULL, 0);
4652
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004653 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004654
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004655 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004656}
4657
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004658struct cmd_conn_lookup {
4659 struct hci_conn *conn;
4660 bool valid_tx_power;
4661 u8 mgmt_status;
4662};
4663
4664static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4665{
4666 struct cmd_conn_lookup *match = data;
4667 struct mgmt_cp_get_conn_info *cp;
4668 struct mgmt_rp_get_conn_info rp;
4669 struct hci_conn *conn = cmd->user_data;
4670
4671 if (conn != match->conn)
4672 return;
4673
4674 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4675
4676 memset(&rp, 0, sizeof(rp));
4677 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4678 rp.addr.type = cp->addr.type;
4679
4680 if (!match->mgmt_status) {
4681 rp.rssi = conn->rssi;
4682
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004683 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004684 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004685 rp.max_tx_power = conn->max_tx_power;
4686 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004687 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004688 rp.max_tx_power = HCI_TX_POWER_INVALID;
4689 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004690 }
4691
4692 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4693 match->mgmt_status, &rp, sizeof(rp));
4694
4695 hci_conn_drop(conn);
4696
4697 mgmt_pending_remove(cmd);
4698}
4699
4700static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4701{
4702 struct hci_cp_read_rssi *cp;
4703 struct hci_conn *conn;
4704 struct cmd_conn_lookup match;
4705 u16 handle;
4706
4707 BT_DBG("status 0x%02x", status);
4708
4709 hci_dev_lock(hdev);
4710
4711 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004712 * otherwise we assume it's not valid. At the moment we assume that
4713 * either both or none of current and max values are valid to keep code
4714 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004715 */
4716 match.valid_tx_power = !status;
4717
4718 /* Commands sent in request are either Read RSSI or Read Transmit Power
4719 * Level so we check which one was last sent to retrieve connection
4720 * handle. Both commands have handle as first parameter so it's safe to
4721 * cast data on the same command struct.
4722 *
4723 * First command sent is always Read RSSI and we fail only if it fails.
4724 * In other case we simply override error to indicate success as we
4725 * already remembered if TX power value is actually valid.
4726 */
4727 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4728 if (!cp) {
4729 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4730 status = 0;
4731 }
4732
4733 if (!cp) {
4734 BT_ERR("invalid sent_cmd in response");
4735 goto unlock;
4736 }
4737
4738 handle = __le16_to_cpu(cp->handle);
4739 conn = hci_conn_hash_lookup_handle(hdev, handle);
4740 if (!conn) {
4741 BT_ERR("unknown handle (%d) in response", handle);
4742 goto unlock;
4743 }
4744
4745 match.conn = conn;
4746 match.mgmt_status = mgmt_status(status);
4747
4748 /* Cache refresh is complete, now reply for mgmt request for given
4749 * connection only.
4750 */
4751 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4752 get_conn_info_complete, &match);
4753
4754unlock:
4755 hci_dev_unlock(hdev);
4756}
4757
4758static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4759 u16 len)
4760{
4761 struct mgmt_cp_get_conn_info *cp = data;
4762 struct mgmt_rp_get_conn_info rp;
4763 struct hci_conn *conn;
4764 unsigned long conn_info_age;
4765 int err = 0;
4766
4767 BT_DBG("%s", hdev->name);
4768
4769 memset(&rp, 0, sizeof(rp));
4770 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4771 rp.addr.type = cp->addr.type;
4772
4773 if (!bdaddr_type_is_valid(cp->addr.type))
4774 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4775 MGMT_STATUS_INVALID_PARAMS,
4776 &rp, sizeof(rp));
4777
4778 hci_dev_lock(hdev);
4779
4780 if (!hdev_is_powered(hdev)) {
4781 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4782 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4783 goto unlock;
4784 }
4785
4786 if (cp->addr.type == BDADDR_BREDR)
4787 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4788 &cp->addr.bdaddr);
4789 else
4790 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4791
4792 if (!conn || conn->state != BT_CONNECTED) {
4793 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4794 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4795 goto unlock;
4796 }
4797
4798 /* To avoid client trying to guess when to poll again for information we
4799 * calculate conn info age as random value between min/max set in hdev.
4800 */
4801 conn_info_age = hdev->conn_info_min_age +
4802 prandom_u32_max(hdev->conn_info_max_age -
4803 hdev->conn_info_min_age);
4804
4805 /* Query controller to refresh cached values if they are too old or were
4806 * never read.
4807 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004808 if (time_after(jiffies, conn->conn_info_timestamp +
4809 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004810 !conn->conn_info_timestamp) {
4811 struct hci_request req;
4812 struct hci_cp_read_tx_power req_txp_cp;
4813 struct hci_cp_read_rssi req_rssi_cp;
4814 struct pending_cmd *cmd;
4815
4816 hci_req_init(&req, hdev);
4817 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4818 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4819 &req_rssi_cp);
4820
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004821 /* For LE links TX power does not change thus we don't need to
4822 * query for it once value is known.
4823 */
4824 if (!bdaddr_type_is_le(cp->addr.type) ||
4825 conn->tx_power == HCI_TX_POWER_INVALID) {
4826 req_txp_cp.handle = cpu_to_le16(conn->handle);
4827 req_txp_cp.type = 0x00;
4828 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4829 sizeof(req_txp_cp), &req_txp_cp);
4830 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004831
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004832 /* Max TX power needs to be read only once per connection */
4833 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4834 req_txp_cp.handle = cpu_to_le16(conn->handle);
4835 req_txp_cp.type = 0x01;
4836 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4837 sizeof(req_txp_cp), &req_txp_cp);
4838 }
4839
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004840 err = hci_req_run(&req, conn_info_refresh_complete);
4841 if (err < 0)
4842 goto unlock;
4843
4844 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4845 data, len);
4846 if (!cmd) {
4847 err = -ENOMEM;
4848 goto unlock;
4849 }
4850
4851 hci_conn_hold(conn);
4852 cmd->user_data = conn;
4853
4854 conn->conn_info_timestamp = jiffies;
4855 } else {
4856 /* Cache is valid, just reply with values cached in hci_conn */
4857 rp.rssi = conn->rssi;
4858 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004859 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004860
4861 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4862 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4863 }
4864
4865unlock:
4866 hci_dev_unlock(hdev);
4867 return err;
4868}
4869
Johan Hedberg95868422014-06-28 17:54:07 +03004870static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4871{
4872 struct mgmt_cp_get_clock_info *cp;
4873 struct mgmt_rp_get_clock_info rp;
4874 struct hci_cp_read_clock *hci_cp;
4875 struct pending_cmd *cmd;
4876 struct hci_conn *conn;
4877
4878 BT_DBG("%s status %u", hdev->name, status);
4879
4880 hci_dev_lock(hdev);
4881
4882 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4883 if (!hci_cp)
4884 goto unlock;
4885
4886 if (hci_cp->which) {
4887 u16 handle = __le16_to_cpu(hci_cp->handle);
4888 conn = hci_conn_hash_lookup_handle(hdev, handle);
4889 } else {
4890 conn = NULL;
4891 }
4892
4893 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4894 if (!cmd)
4895 goto unlock;
4896
4897 cp = cmd->param;
4898
4899 memset(&rp, 0, sizeof(rp));
4900 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4901
4902 if (status)
4903 goto send_rsp;
4904
4905 rp.local_clock = cpu_to_le32(hdev->clock);
4906
4907 if (conn) {
4908 rp.piconet_clock = cpu_to_le32(conn->clock);
4909 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4910 }
4911
4912send_rsp:
4913 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4914 &rp, sizeof(rp));
4915 mgmt_pending_remove(cmd);
4916 if (conn)
4917 hci_conn_drop(conn);
4918
4919unlock:
4920 hci_dev_unlock(hdev);
4921}
4922
4923static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4924 u16 len)
4925{
4926 struct mgmt_cp_get_clock_info *cp = data;
4927 struct mgmt_rp_get_clock_info rp;
4928 struct hci_cp_read_clock hci_cp;
4929 struct pending_cmd *cmd;
4930 struct hci_request req;
4931 struct hci_conn *conn;
4932 int err;
4933
4934 BT_DBG("%s", hdev->name);
4935
4936 memset(&rp, 0, sizeof(rp));
4937 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4938 rp.addr.type = cp->addr.type;
4939
4940 if (cp->addr.type != BDADDR_BREDR)
4941 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4942 MGMT_STATUS_INVALID_PARAMS,
4943 &rp, sizeof(rp));
4944
4945 hci_dev_lock(hdev);
4946
4947 if (!hdev_is_powered(hdev)) {
4948 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4949 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4950 goto unlock;
4951 }
4952
4953 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4954 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4955 &cp->addr.bdaddr);
4956 if (!conn || conn->state != BT_CONNECTED) {
4957 err = cmd_complete(sk, hdev->id,
4958 MGMT_OP_GET_CLOCK_INFO,
4959 MGMT_STATUS_NOT_CONNECTED,
4960 &rp, sizeof(rp));
4961 goto unlock;
4962 }
4963 } else {
4964 conn = NULL;
4965 }
4966
4967 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4968 if (!cmd) {
4969 err = -ENOMEM;
4970 goto unlock;
4971 }
4972
4973 hci_req_init(&req, hdev);
4974
4975 memset(&hci_cp, 0, sizeof(hci_cp));
4976 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4977
4978 if (conn) {
4979 hci_conn_hold(conn);
4980 cmd->user_data = conn;
4981
4982 hci_cp.handle = cpu_to_le16(conn->handle);
4983 hci_cp.which = 0x01; /* Piconet clock */
4984 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4985 }
4986
4987 err = hci_req_run(&req, get_clock_info_complete);
4988 if (err < 0)
4989 mgmt_pending_remove(cmd);
4990
4991unlock:
4992 hci_dev_unlock(hdev);
4993 return err;
4994}
4995
Marcel Holtmann8afef092014-06-29 22:28:34 +02004996static void device_added(struct sock *sk, struct hci_dev *hdev,
4997 bdaddr_t *bdaddr, u8 type, u8 action)
4998{
4999 struct mgmt_ev_device_added ev;
5000
5001 bacpy(&ev.addr.bdaddr, bdaddr);
5002 ev.addr.type = type;
5003 ev.action = action;
5004
5005 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5006}
5007
Marcel Holtmann2faade52014-06-29 19:44:03 +02005008static int add_device(struct sock *sk, struct hci_dev *hdev,
5009 void *data, u16 len)
5010{
5011 struct mgmt_cp_add_device *cp = data;
5012 u8 auto_conn, addr_type;
5013 int err;
5014
5015 BT_DBG("%s", hdev->name);
5016
5017 if (!bdaddr_type_is_le(cp->addr.type) ||
5018 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5019 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5020 MGMT_STATUS_INVALID_PARAMS,
5021 &cp->addr, sizeof(cp->addr));
5022
5023 if (cp->action != 0x00 && cp->action != 0x01)
5024 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5025 MGMT_STATUS_INVALID_PARAMS,
5026 &cp->addr, sizeof(cp->addr));
5027
5028 hci_dev_lock(hdev);
5029
5030 if (cp->addr.type == BDADDR_LE_PUBLIC)
5031 addr_type = ADDR_LE_DEV_PUBLIC;
5032 else
5033 addr_type = ADDR_LE_DEV_RANDOM;
5034
5035 if (cp->action)
5036 auto_conn = HCI_AUTO_CONN_ALWAYS;
5037 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005038 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005039
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005040 /* If the connection parameters don't exist for this device,
5041 * they will be created and configured with defaults.
5042 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005043 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5044 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005045 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5046 MGMT_STATUS_FAILED,
5047 &cp->addr, sizeof(cp->addr));
5048 goto unlock;
5049 }
5050
Marcel Holtmann8afef092014-06-29 22:28:34 +02005051 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5052
Marcel Holtmann2faade52014-06-29 19:44:03 +02005053 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5054 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5055
5056unlock:
5057 hci_dev_unlock(hdev);
5058 return err;
5059}
5060
Marcel Holtmann8afef092014-06-29 22:28:34 +02005061static void device_removed(struct sock *sk, struct hci_dev *hdev,
5062 bdaddr_t *bdaddr, u8 type)
5063{
5064 struct mgmt_ev_device_removed ev;
5065
5066 bacpy(&ev.addr.bdaddr, bdaddr);
5067 ev.addr.type = type;
5068
5069 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5070}
5071
Marcel Holtmann2faade52014-06-29 19:44:03 +02005072static int remove_device(struct sock *sk, struct hci_dev *hdev,
5073 void *data, u16 len)
5074{
5075 struct mgmt_cp_remove_device *cp = data;
5076 int err;
5077
5078 BT_DBG("%s", hdev->name);
5079
5080 hci_dev_lock(hdev);
5081
5082 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005083 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005084 u8 addr_type;
5085
5086 if (!bdaddr_type_is_le(cp->addr.type)) {
5087 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5088 MGMT_STATUS_INVALID_PARAMS,
5089 &cp->addr, sizeof(cp->addr));
5090 goto unlock;
5091 }
5092
5093 if (cp->addr.type == BDADDR_LE_PUBLIC)
5094 addr_type = ADDR_LE_DEV_PUBLIC;
5095 else
5096 addr_type = ADDR_LE_DEV_RANDOM;
5097
Johan Hedbergc71593d2014-07-02 17:37:28 +03005098 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5099 addr_type);
5100 if (!params) {
5101 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5102 MGMT_STATUS_INVALID_PARAMS,
5103 &cp->addr, sizeof(cp->addr));
5104 goto unlock;
5105 }
5106
5107 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5108 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5109 MGMT_STATUS_INVALID_PARAMS,
5110 &cp->addr, sizeof(cp->addr));
5111 goto unlock;
5112 }
5113
5114 hci_pend_le_conn_del(hdev, &cp->addr.bdaddr, addr_type);
5115 list_del(&params->list);
5116 kfree(params);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005117
5118 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005119 } else {
5120 if (cp->addr.type) {
5121 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5122 MGMT_STATUS_INVALID_PARAMS,
5123 &cp->addr, sizeof(cp->addr));
5124 goto unlock;
5125 }
5126
Johan Hedbergc71593d2014-07-02 17:37:28 +03005127 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005128 }
5129
5130 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5131 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5132
5133unlock:
5134 hci_dev_unlock(hdev);
5135 return err;
5136}
5137
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005138static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5139 u16 len)
5140{
5141 struct mgmt_cp_load_conn_param *cp = data;
5142 u16 param_count, expected_len;
5143 int i;
5144
5145 if (!lmp_le_capable(hdev))
5146 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5147 MGMT_STATUS_NOT_SUPPORTED);
5148
5149 param_count = __le16_to_cpu(cp->param_count);
5150
5151 expected_len = sizeof(*cp) + param_count *
5152 sizeof(struct mgmt_conn_param);
5153 if (expected_len != len) {
5154 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5155 expected_len, len);
5156 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5157 MGMT_STATUS_INVALID_PARAMS);
5158 }
5159
5160 BT_DBG("%s param_count %u", hdev->name, param_count);
5161
5162 hci_dev_lock(hdev);
5163
5164 hci_conn_params_clear_disabled(hdev);
5165
5166 for (i = 0; i < param_count; i++) {
5167 struct mgmt_conn_param *param = &cp->params[i];
5168 struct hci_conn_params *hci_param;
5169 u16 min, max, latency, timeout;
5170 u8 addr_type;
5171
5172 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5173 param->addr.type);
5174
5175 if (param->addr.type == BDADDR_LE_PUBLIC) {
5176 addr_type = ADDR_LE_DEV_PUBLIC;
5177 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5178 addr_type = ADDR_LE_DEV_RANDOM;
5179 } else {
5180 BT_ERR("Ignoring invalid connection parameters");
5181 continue;
5182 }
5183
5184 min = le16_to_cpu(param->min_interval);
5185 max = le16_to_cpu(param->max_interval);
5186 latency = le16_to_cpu(param->latency);
5187 timeout = le16_to_cpu(param->timeout);
5188
5189 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5190 min, max, latency, timeout);
5191
5192 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5193 BT_ERR("Ignoring invalid connection parameters");
5194 continue;
5195 }
5196
5197 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5198 addr_type);
5199 if (!hci_param) {
5200 BT_ERR("Failed to add connection parameters");
5201 continue;
5202 }
5203
5204 hci_param->conn_min_interval = min;
5205 hci_param->conn_max_interval = max;
5206 hci_param->conn_latency = latency;
5207 hci_param->supervision_timeout = timeout;
5208 }
5209
5210 hci_dev_unlock(hdev);
5211
5212 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5213}
5214
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005215static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005216 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5217 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005218 bool var_len;
5219 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005220} mgmt_handlers[] = {
5221 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005222 { read_version, false, MGMT_READ_VERSION_SIZE },
5223 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5224 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5225 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5226 { set_powered, false, MGMT_SETTING_SIZE },
5227 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5228 { set_connectable, false, MGMT_SETTING_SIZE },
5229 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5230 { set_pairable, false, MGMT_SETTING_SIZE },
5231 { set_link_security, false, MGMT_SETTING_SIZE },
5232 { set_ssp, false, MGMT_SETTING_SIZE },
5233 { set_hs, false, MGMT_SETTING_SIZE },
5234 { set_le, false, MGMT_SETTING_SIZE },
5235 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5236 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5237 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5238 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5239 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5240 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5241 { disconnect, false, MGMT_DISCONNECT_SIZE },
5242 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5243 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5244 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5245 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5246 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5247 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5248 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5249 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5250 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5251 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5252 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5253 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005254 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005255 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5256 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5257 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5258 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5259 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5260 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005261 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005262 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005263 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005264 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005265 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005266 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005267 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005268 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005269 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005270 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005271 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005272 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5273 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005274 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005275};
5276
Johan Hedberg03811012010-12-08 00:21:06 +02005277int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5278{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005279 void *buf;
5280 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005281 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005282 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005283 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005284 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005285 int err;
5286
5287 BT_DBG("got %zu bytes", msglen);
5288
5289 if (msglen < sizeof(*hdr))
5290 return -EINVAL;
5291
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005292 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005293 if (!buf)
5294 return -ENOMEM;
5295
5296 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5297 err = -EFAULT;
5298 goto done;
5299 }
5300
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005301 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005302 opcode = __le16_to_cpu(hdr->opcode);
5303 index = __le16_to_cpu(hdr->index);
5304 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005305
5306 if (len != msglen - sizeof(*hdr)) {
5307 err = -EINVAL;
5308 goto done;
5309 }
5310
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005311 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005312 hdev = hci_dev_get(index);
5313 if (!hdev) {
5314 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005315 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005316 goto done;
5317 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005318
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005319 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005320 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5321 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005322 err = cmd_status(sk, index, opcode,
5323 MGMT_STATUS_INVALID_INDEX);
5324 goto done;
5325 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005326 }
5327
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005328 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005329 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005330 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005331 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005332 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005333 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005334 }
5335
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005336 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005337 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005338 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005339 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005340 goto done;
5341 }
5342
Johan Hedbergbe22b542012-03-01 22:24:41 +02005343 handler = &mgmt_handlers[opcode];
5344
5345 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005346 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005347 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005348 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005349 goto done;
5350 }
5351
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005352 if (hdev)
5353 mgmt_init_hdev(sk, hdev);
5354
5355 cp = buf + sizeof(*hdr);
5356
Johan Hedbergbe22b542012-03-01 22:24:41 +02005357 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005358 if (err < 0)
5359 goto done;
5360
Johan Hedberg03811012010-12-08 00:21:06 +02005361 err = msglen;
5362
5363done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005364 if (hdev)
5365 hci_dev_put(hdev);
5366
Johan Hedberg03811012010-12-08 00:21:06 +02005367 kfree(buf);
5368 return err;
5369}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005370
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005371void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005372{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005373 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005374 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005375
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005376 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005377}
5378
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005379void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005380{
Johan Hedberg5f159032012-03-02 03:13:19 +02005381 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005382
Marcel Holtmann1514b892013-10-06 08:25:01 -07005383 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005384 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005385
Johan Hedberg744cf192011-11-08 20:40:14 +02005386 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005387
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005388 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005389}
5390
Andre Guedes6046dc32014-02-26 20:21:51 -03005391/* This function requires the caller holds hdev->lock */
5392static void restart_le_auto_conns(struct hci_dev *hdev)
5393{
5394 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005395 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005396
5397 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005398 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005399 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005400 added = true;
5401 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005402 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005403
5404 /* Calling hci_pend_le_conn_add will actually already trigger
5405 * background scanning when needed. So no need to trigger it
5406 * just another time.
5407 *
5408 * This check is here to avoid an unneeded restart of the
5409 * passive scanning. Since this is during the controller
5410 * power up phase the duplicate filtering is not an issue.
5411 */
5412 if (added)
5413 return;
5414
5415 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005416}
5417
Johan Hedberg229ab392013-03-15 17:06:53 -05005418static void powered_complete(struct hci_dev *hdev, u8 status)
5419{
5420 struct cmd_lookup match = { NULL, hdev };
5421
5422 BT_DBG("status 0x%02x", status);
5423
5424 hci_dev_lock(hdev);
5425
Andre Guedes6046dc32014-02-26 20:21:51 -03005426 restart_le_auto_conns(hdev);
5427
Johan Hedberg229ab392013-03-15 17:06:53 -05005428 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5429
5430 new_settings(hdev, match.sk);
5431
5432 hci_dev_unlock(hdev);
5433
5434 if (match.sk)
5435 sock_put(match.sk);
5436}
5437
Johan Hedberg70da6242013-03-15 17:06:51 -05005438static int powered_update_hci(struct hci_dev *hdev)
5439{
Johan Hedberg890ea892013-03-15 17:06:52 -05005440 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005441 u8 link_sec;
5442
Johan Hedberg890ea892013-03-15 17:06:52 -05005443 hci_req_init(&req, hdev);
5444
Johan Hedberg70da6242013-03-15 17:06:51 -05005445 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5446 !lmp_host_ssp_capable(hdev)) {
5447 u8 ssp = 1;
5448
Johan Hedberg890ea892013-03-15 17:06:52 -05005449 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005450 }
5451
Johan Hedbergc73eee92013-04-19 18:35:21 +03005452 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5453 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005454 struct hci_cp_write_le_host_supported cp;
5455
5456 cp.le = 1;
5457 cp.simul = lmp_le_br_capable(hdev);
5458
5459 /* Check first if we already have the right
5460 * host state (host features set)
5461 */
5462 if (cp.le != lmp_host_le_capable(hdev) ||
5463 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005464 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5465 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005466 }
5467
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005468 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005469 /* Make sure the controller has a good default for
5470 * advertising data. This also applies to the case
5471 * where BR/EDR was toggled during the AUTO_OFF phase.
5472 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005473 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005474 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005475 update_scan_rsp_data(&req);
5476 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005477
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005478 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5479 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005480 }
5481
Johan Hedberg70da6242013-03-15 17:06:51 -05005482 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5483 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005484 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5485 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005486
5487 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005488 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5489 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005490 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005491 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005492 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005493 }
5494
Johan Hedberg229ab392013-03-15 17:06:53 -05005495 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005496}
5497
Johan Hedberg744cf192011-11-08 20:40:14 +02005498int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005499{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005500 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005501 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5502 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005503 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005504
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005505 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5506 return 0;
5507
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005508 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005509 if (powered_update_hci(hdev) == 0)
5510 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005511
Johan Hedberg229ab392013-03-15 17:06:53 -05005512 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5513 &match);
5514 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005515 }
5516
Johan Hedberg229ab392013-03-15 17:06:53 -05005517 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5518 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5519
5520 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5521 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5522 zero_cod, sizeof(zero_cod), NULL);
5523
5524new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005525 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005526
5527 if (match.sk)
5528 sock_put(match.sk);
5529
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005530 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005531}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005532
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005533void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005534{
5535 struct pending_cmd *cmd;
5536 u8 status;
5537
5538 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5539 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005540 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005541
5542 if (err == -ERFKILL)
5543 status = MGMT_STATUS_RFKILLED;
5544 else
5545 status = MGMT_STATUS_FAILED;
5546
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005547 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005548
5549 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005550}
5551
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005552void mgmt_discoverable_timeout(struct hci_dev *hdev)
5553{
5554 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005555
5556 hci_dev_lock(hdev);
5557
5558 /* When discoverable timeout triggers, then just make sure
5559 * the limited discoverable flag is cleared. Even in the case
5560 * of a timeout triggered from general discoverable, it is
5561 * safe to unconditionally clear the flag.
5562 */
5563 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005564 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005565
5566 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005567 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5568 u8 scan = SCAN_PAGE;
5569 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5570 sizeof(scan), &scan);
5571 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005572 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005573 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005574 hci_req_run(&req, NULL);
5575
5576 hdev->discov_timeout = 0;
5577
Johan Hedberg9a43e252013-10-20 19:00:07 +03005578 new_settings(hdev, NULL);
5579
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005580 hci_dev_unlock(hdev);
5581}
5582
Marcel Holtmann86a75642013-10-15 06:33:54 -07005583void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005584{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005585 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005586
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005587 /* Nothing needed here if there's a pending command since that
5588 * commands request completion callback takes care of everything
5589 * necessary.
5590 */
5591 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005592 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005593
Johan Hedbergbd107992014-02-24 14:52:19 +02005594 /* Powering off may clear the scan mode - don't let that interfere */
5595 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5596 return;
5597
Johan Hedberg9a43e252013-10-20 19:00:07 +03005598 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005599 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005600 } else {
5601 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005602 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005603 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005604
Johan Hedberg9a43e252013-10-20 19:00:07 +03005605 if (changed) {
5606 struct hci_request req;
5607
5608 /* In case this change in discoverable was triggered by
5609 * a disabling of connectable there could be a need to
5610 * update the advertising flags.
5611 */
5612 hci_req_init(&req, hdev);
5613 update_adv_data(&req);
5614 hci_req_run(&req, NULL);
5615
Marcel Holtmann86a75642013-10-15 06:33:54 -07005616 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005617 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005618}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005619
Marcel Holtmanna3309162013-10-15 06:33:55 -07005620void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005621{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005622 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005623
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005624 /* Nothing needed here if there's a pending command since that
5625 * commands request completion callback takes care of everything
5626 * necessary.
5627 */
5628 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005629 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005630
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005631 /* Powering off may clear the scan mode - don't let that interfere */
5632 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5633 return;
5634
Marcel Holtmanna3309162013-10-15 06:33:55 -07005635 if (connectable)
5636 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5637 else
5638 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005639
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005640 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005641 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005642}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005643
Johan Hedberg778b2352014-02-24 14:52:17 +02005644void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5645{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005646 /* Powering off may stop advertising - don't let that interfere */
5647 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5648 return;
5649
Johan Hedberg778b2352014-02-24 14:52:17 +02005650 if (advertising)
5651 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5652 else
5653 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5654}
5655
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005656void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005657{
Johan Hedbergca69b792011-11-11 18:10:00 +02005658 u8 mgmt_err = mgmt_status(status);
5659
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005660 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005661 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005662 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005663
5664 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005665 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005666 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005667}
5668
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005669void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5670 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005671{
Johan Hedberg86742e12011-11-07 23:13:38 +02005672 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005673
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005674 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005675
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005676 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005677 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005678 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005679 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005680 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005681 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005682
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005683 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005684}
Johan Hedbergf7520542011-01-20 12:34:39 +02005685
Johan Hedbergd7b25452014-05-23 13:19:53 +03005686static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5687{
5688 if (ltk->authenticated)
5689 return MGMT_LTK_AUTHENTICATED;
5690
5691 return MGMT_LTK_UNAUTHENTICATED;
5692}
5693
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005694void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005695{
5696 struct mgmt_ev_new_long_term_key ev;
5697
5698 memset(&ev, 0, sizeof(ev));
5699
Marcel Holtmann5192d302014-02-19 17:11:58 -08005700 /* Devices using resolvable or non-resolvable random addresses
5701 * without providing an indentity resolving key don't require
5702 * to store long term keys. Their addresses will change the
5703 * next time around.
5704 *
5705 * Only when a remote device provides an identity address
5706 * make sure the long term key is stored. If the remote
5707 * identity is known, the long term keys are internally
5708 * mapped to the identity address. So allow static random
5709 * and public addresses here.
5710 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005711 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5712 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5713 ev.store_hint = 0x00;
5714 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005715 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005716
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005717 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005718 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005719 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005720 ev.key.enc_size = key->enc_size;
5721 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005722 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005723
Johan Hedberg2ceba532014-06-16 19:25:16 +03005724 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005725 ev.key.master = 1;
5726
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005727 memcpy(ev.key.val, key->val, sizeof(key->val));
5728
Marcel Holtmann083368f2013-10-15 14:26:29 -07005729 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005730}
5731
Johan Hedberg95fbac82014-02-19 15:18:31 +02005732void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5733{
5734 struct mgmt_ev_new_irk ev;
5735
5736 memset(&ev, 0, sizeof(ev));
5737
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005738 /* For identity resolving keys from devices that are already
5739 * using a public address or static random address, do not
5740 * ask for storing this key. The identity resolving key really
5741 * is only mandatory for devices using resovlable random
5742 * addresses.
5743 *
5744 * Storing all identity resolving keys has the downside that
5745 * they will be also loaded on next boot of they system. More
5746 * identity resolving keys, means more time during scanning is
5747 * needed to actually resolve these addresses.
5748 */
5749 if (bacmp(&irk->rpa, BDADDR_ANY))
5750 ev.store_hint = 0x01;
5751 else
5752 ev.store_hint = 0x00;
5753
Johan Hedberg95fbac82014-02-19 15:18:31 +02005754 bacpy(&ev.rpa, &irk->rpa);
5755 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5756 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5757 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5758
5759 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5760}
5761
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005762void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5763 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005764{
5765 struct mgmt_ev_new_csrk ev;
5766
5767 memset(&ev, 0, sizeof(ev));
5768
5769 /* Devices using resolvable or non-resolvable random addresses
5770 * without providing an indentity resolving key don't require
5771 * to store signature resolving keys. Their addresses will change
5772 * the next time around.
5773 *
5774 * Only when a remote device provides an identity address
5775 * make sure the signature resolving key is stored. So allow
5776 * static random and public addresses here.
5777 */
5778 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5779 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5780 ev.store_hint = 0x00;
5781 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005782 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005783
5784 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5785 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5786 ev.key.master = csrk->master;
5787 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5788
5789 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5790}
5791
Andre Guedesffb5a8272014-07-01 18:10:11 -03005792void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005793 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5794 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005795{
5796 struct mgmt_ev_new_conn_param ev;
5797
Johan Hedbergc103aea2014-07-02 17:37:34 +03005798 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5799 return;
5800
Andre Guedesffb5a8272014-07-01 18:10:11 -03005801 memset(&ev, 0, sizeof(ev));
5802 bacpy(&ev.addr.bdaddr, bdaddr);
5803 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005804 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005805 ev.min_interval = cpu_to_le16(min_interval);
5806 ev.max_interval = cpu_to_le16(max_interval);
5807 ev.latency = cpu_to_le16(latency);
5808 ev.timeout = cpu_to_le16(timeout);
5809
5810 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5811}
5812
Marcel Holtmann94933992013-10-15 10:26:39 -07005813static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5814 u8 data_len)
5815{
5816 eir[eir_len++] = sizeof(type) + data_len;
5817 eir[eir_len++] = type;
5818 memcpy(&eir[eir_len], data, data_len);
5819 eir_len += data_len;
5820
5821 return eir_len;
5822}
5823
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005824void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5825 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5826 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005827{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005828 char buf[512];
5829 struct mgmt_ev_device_connected *ev = (void *) buf;
5830 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005831
Johan Hedbergb644ba32012-01-17 21:48:47 +02005832 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005833 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005834
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005835 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005836
Johan Hedbergb644ba32012-01-17 21:48:47 +02005837 if (name_len > 0)
5838 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005839 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005840
5841 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005842 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005843 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005844
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005845 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005846
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005847 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5848 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005849}
5850
Johan Hedberg8962ee72011-01-20 12:40:27 +02005851static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5852{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005853 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005854 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005855 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005856
Johan Hedberg88c3df12012-02-09 14:27:38 +02005857 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5858 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005859
Johan Hedbergaee9b212012-02-18 15:07:59 +02005860 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005861 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005862
5863 *sk = cmd->sk;
5864 sock_hold(*sk);
5865
Johan Hedberga664b5b2011-02-19 12:06:02 -03005866 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005867}
5868
Johan Hedberg124f6e32012-02-09 13:50:12 +02005869static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005870{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005871 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005872 struct mgmt_cp_unpair_device *cp = cmd->param;
5873 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005874
5875 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005876 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5877 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005878
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005879 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5880
Johan Hedbergaee9b212012-02-18 15:07:59 +02005881 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005882
5883 mgmt_pending_remove(cmd);
5884}
5885
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005886void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005887 u8 link_type, u8 addr_type, u8 reason,
5888 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005889{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005890 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005891 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005892 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005893
Johan Hedberg8b064a32014-02-24 14:52:22 +02005894 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5895 if (power_off) {
5896 struct mgmt_mode *cp = power_off->param;
5897
5898 /* The connection is still in hci_conn_hash so test for 1
5899 * instead of 0 to know if this is the last one.
5900 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005901 if (!cp->val && hci_conn_count(hdev) == 1) {
5902 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005903 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005904 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005905 }
5906
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005907 if (!mgmt_connected)
5908 return;
5909
Andre Guedes57eb7762013-10-30 19:01:41 -03005910 if (link_type != ACL_LINK && link_type != LE_LINK)
5911 return;
5912
Johan Hedberg744cf192011-11-08 20:40:14 +02005913 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005914
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005915 bacpy(&ev.addr.bdaddr, bdaddr);
5916 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5917 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005918
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005919 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005920
5921 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005922 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005923
Johan Hedberg124f6e32012-02-09 13:50:12 +02005924 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005925 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005926}
5927
Marcel Holtmann78929242013-10-06 23:55:47 -07005928void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5929 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005930{
Andre Guedes3655bba2013-10-30 19:01:40 -03005931 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5932 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005933 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005934 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005935
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005936 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5937 hdev);
5938
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005939 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005940 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005941 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005942
Andre Guedes3655bba2013-10-30 19:01:40 -03005943 cp = cmd->param;
5944
5945 if (bacmp(bdaddr, &cp->addr.bdaddr))
5946 return;
5947
5948 if (cp->addr.type != bdaddr_type)
5949 return;
5950
Johan Hedberg88c3df12012-02-09 14:27:38 +02005951 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005952 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005953
Marcel Holtmann78929242013-10-06 23:55:47 -07005954 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5955 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005956
Johan Hedberga664b5b2011-02-19 12:06:02 -03005957 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005958}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005959
Marcel Holtmann445608d2013-10-06 23:55:48 -07005960void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5961 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005962{
5963 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005964 struct pending_cmd *power_off;
5965
5966 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5967 if (power_off) {
5968 struct mgmt_mode *cp = power_off->param;
5969
5970 /* The connection is still in hci_conn_hash so test for 1
5971 * instead of 0 to know if this is the last one.
5972 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005973 if (!cp->val && hci_conn_count(hdev) == 1) {
5974 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005975 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005976 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005977 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005978
Johan Hedberg4c659c32011-11-07 23:13:39 +02005979 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005980 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005981 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005982
Marcel Holtmann445608d2013-10-06 23:55:48 -07005983 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005984}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005985
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005986void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005987{
5988 struct mgmt_ev_pin_code_request ev;
5989
Johan Hedbergd8457692012-02-17 14:24:57 +02005990 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005991 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005992 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005993
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005994 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005995}
5996
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005997void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5998 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005999{
6000 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006001 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006002
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006003 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006004 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006005 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006006
Johan Hedbergd8457692012-02-17 14:24:57 +02006007 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006008 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006009
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006010 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6011 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006012
Johan Hedberga664b5b2011-02-19 12:06:02 -03006013 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006014}
6015
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006016void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6017 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006018{
6019 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006020 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006021
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006022 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006023 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006024 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006025
Johan Hedbergd8457692012-02-17 14:24:57 +02006026 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006027 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006028
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006029 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6030 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006031
Johan Hedberga664b5b2011-02-19 12:06:02 -03006032 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006033}
Johan Hedberga5c29682011-02-19 12:05:57 -03006034
Johan Hedberg744cf192011-11-08 20:40:14 +02006035int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006036 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006037 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006038{
6039 struct mgmt_ev_user_confirm_request ev;
6040
Johan Hedberg744cf192011-11-08 20:40:14 +02006041 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006042
Johan Hedberg272d90d2012-02-09 15:26:12 +02006043 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006044 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006045 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006046 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006047
Johan Hedberg744cf192011-11-08 20:40:14 +02006048 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006049 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006050}
6051
Johan Hedberg272d90d2012-02-09 15:26:12 +02006052int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006053 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006054{
6055 struct mgmt_ev_user_passkey_request ev;
6056
6057 BT_DBG("%s", hdev->name);
6058
Johan Hedberg272d90d2012-02-09 15:26:12 +02006059 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006060 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006061
6062 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006063 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006064}
6065
Brian Gix0df4c182011-11-16 13:53:13 -08006066static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006067 u8 link_type, u8 addr_type, u8 status,
6068 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006069{
6070 struct pending_cmd *cmd;
6071 struct mgmt_rp_user_confirm_reply rp;
6072 int err;
6073
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006074 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006075 if (!cmd)
6076 return -ENOENT;
6077
Johan Hedberg272d90d2012-02-09 15:26:12 +02006078 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006079 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006080 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006081 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006082
Johan Hedberga664b5b2011-02-19 12:06:02 -03006083 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006084
6085 return err;
6086}
6087
Johan Hedberg744cf192011-11-08 20:40:14 +02006088int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006089 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006090{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006091 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006092 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006093}
6094
Johan Hedberg272d90d2012-02-09 15:26:12 +02006095int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006096 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006097{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006098 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006099 status,
6100 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006101}
Johan Hedberg2a611692011-02-19 12:06:00 -03006102
Brian Gix604086b2011-11-23 08:28:33 -08006103int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006104 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006105{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006106 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006107 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006108}
6109
Johan Hedberg272d90d2012-02-09 15:26:12 +02006110int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006111 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006112{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006113 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006114 status,
6115 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006116}
6117
Johan Hedberg92a25252012-09-06 18:39:26 +03006118int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6119 u8 link_type, u8 addr_type, u32 passkey,
6120 u8 entered)
6121{
6122 struct mgmt_ev_passkey_notify ev;
6123
6124 BT_DBG("%s", hdev->name);
6125
6126 bacpy(&ev.addr.bdaddr, bdaddr);
6127 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6128 ev.passkey = __cpu_to_le32(passkey);
6129 ev.entered = entered;
6130
6131 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6132}
6133
Marcel Holtmanne5460992013-10-15 14:26:23 -07006134void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6135 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006136{
6137 struct mgmt_ev_auth_failed ev;
6138
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006139 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006140 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006141 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006142
Marcel Holtmanne5460992013-10-15 14:26:23 -07006143 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006144}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006145
Marcel Holtmann464996a2013-10-15 14:26:24 -07006146void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006147{
6148 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006149 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006150
6151 if (status) {
6152 u8 mgmt_err = mgmt_status(status);
6153 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006154 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006155 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006156 }
6157
Marcel Holtmann464996a2013-10-15 14:26:24 -07006158 if (test_bit(HCI_AUTH, &hdev->flags))
6159 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6160 &hdev->dev_flags);
6161 else
6162 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6163 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006164
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006165 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006166 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006167
Johan Hedberg47990ea2012-02-22 11:58:37 +02006168 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006169 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006170
6171 if (match.sk)
6172 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006173}
6174
Johan Hedberg890ea892013-03-15 17:06:52 -05006175static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006176{
Johan Hedberg890ea892013-03-15 17:06:52 -05006177 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006178 struct hci_cp_write_eir cp;
6179
Johan Hedberg976eb202012-10-24 21:12:01 +03006180 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006181 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006182
Johan Hedbergc80da272012-02-22 15:38:48 +02006183 memset(hdev->eir, 0, sizeof(hdev->eir));
6184
Johan Hedbergcacaf522012-02-21 00:52:42 +02006185 memset(&cp, 0, sizeof(cp));
6186
Johan Hedberg890ea892013-03-15 17:06:52 -05006187 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006188}
6189
Marcel Holtmann3e248562013-10-15 14:26:25 -07006190void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006191{
6192 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006193 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006194 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006195
6196 if (status) {
6197 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006198
6199 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006200 &hdev->dev_flags)) {
6201 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006202 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006203 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006204
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006205 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6206 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006207 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006208 }
6209
6210 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006211 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006212 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006213 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6214 if (!changed)
6215 changed = test_and_clear_bit(HCI_HS_ENABLED,
6216 &hdev->dev_flags);
6217 else
6218 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006219 }
6220
6221 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6222
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006223 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006224 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006225
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006226 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006227 sock_put(match.sk);
6228
Johan Hedberg890ea892013-03-15 17:06:52 -05006229 hci_req_init(&req, hdev);
6230
Johan Hedberg37699722014-06-24 14:00:27 +03006231 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6232 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6233 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6234 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006235 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006236 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006237 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006238 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006239
6240 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006241}
6242
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006243void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6244{
6245 struct cmd_lookup match = { NULL, hdev };
6246 bool changed = false;
6247
6248 if (status) {
6249 u8 mgmt_err = mgmt_status(status);
6250
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006251 if (enable) {
6252 if (test_and_clear_bit(HCI_SC_ENABLED,
6253 &hdev->dev_flags))
6254 new_settings(hdev, NULL);
6255 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6256 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006257
6258 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6259 cmd_status_rsp, &mgmt_err);
6260 return;
6261 }
6262
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006263 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006264 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006265 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006266 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006267 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6268 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006269
6270 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6271 settings_rsp, &match);
6272
6273 if (changed)
6274 new_settings(hdev, match.sk);
6275
6276 if (match.sk)
6277 sock_put(match.sk);
6278}
6279
Johan Hedberg92da6092013-03-15 17:06:55 -05006280static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006281{
6282 struct cmd_lookup *match = data;
6283
Johan Hedberg90e70452012-02-23 23:09:40 +02006284 if (match->sk == NULL) {
6285 match->sk = cmd->sk;
6286 sock_hold(match->sk);
6287 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006288}
6289
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006290void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6291 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006292{
Johan Hedberg90e70452012-02-23 23:09:40 +02006293 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006294
Johan Hedberg92da6092013-03-15 17:06:55 -05006295 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6296 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6297 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006298
6299 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006300 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6301 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006302
6303 if (match.sk)
6304 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006305}
6306
Marcel Holtmann7667da32013-10-15 14:26:27 -07006307void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006308{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006309 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006310 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006311
Johan Hedberg13928972013-03-15 17:07:00 -05006312 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006313 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006314
6315 memset(&ev, 0, sizeof(ev));
6316 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006317 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006318
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006319 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006320 if (!cmd) {
6321 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006322
Johan Hedberg13928972013-03-15 17:07:00 -05006323 /* If this is a HCI command related to powering on the
6324 * HCI dev don't send any mgmt signals.
6325 */
6326 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006327 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006328 }
6329
Marcel Holtmann7667da32013-10-15 14:26:27 -07006330 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6331 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006332}
Szymon Jancc35938b2011-03-22 13:12:21 +01006333
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006334void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6335 u8 *randomizer192, u8 *hash256,
6336 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006337{
6338 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006339
Johan Hedberg744cf192011-11-08 20:40:14 +02006340 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006341
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006342 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006343 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006344 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006345
6346 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006347 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6348 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006349 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006350 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6351 hash256 && randomizer256) {
6352 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006353
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006354 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6355 memcpy(rp.randomizer192, randomizer192,
6356 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006357
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006358 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6359 memcpy(rp.randomizer256, randomizer256,
6360 sizeof(rp.randomizer256));
6361
6362 cmd_complete(cmd->sk, hdev->id,
6363 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6364 &rp, sizeof(rp));
6365 } else {
6366 struct mgmt_rp_read_local_oob_data rp;
6367
6368 memcpy(rp.hash, hash192, sizeof(rp.hash));
6369 memcpy(rp.randomizer, randomizer192,
6370 sizeof(rp.randomizer));
6371
6372 cmd_complete(cmd->sk, hdev->id,
6373 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6374 &rp, sizeof(rp));
6375 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006376 }
6377
6378 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006379}
Johan Hedberge17acd42011-03-30 23:57:16 +03006380
Marcel Holtmann901801b2013-10-06 23:55:51 -07006381void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006382 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6383 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006384{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006385 char buf[512];
6386 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006387 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006388 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006389
Andre Guedes12602d02013-04-30 15:29:40 -03006390 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006391 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006392
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006393 /* Make sure that the buffer is big enough. The 5 extra bytes
6394 * are for the potential CoD field.
6395 */
6396 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006397 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006398
Johan Hedberg1dc06092012-01-15 21:01:23 +02006399 memset(buf, 0, sizeof(buf));
6400
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006401 irk = hci_get_irk(hdev, bdaddr, addr_type);
6402 if (irk) {
6403 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6404 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6405 } else {
6406 bacpy(&ev->addr.bdaddr, bdaddr);
6407 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6408 }
6409
Johan Hedberge319d2e2012-01-15 19:51:59 +02006410 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006411 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006412
Johan Hedberg1dc06092012-01-15 21:01:23 +02006413 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006414 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006415
Johan Hedberg1dc06092012-01-15 21:01:23 +02006416 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6417 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006418 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006419
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006420 if (scan_rsp_len > 0)
6421 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6422
6423 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6424 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006425
Marcel Holtmann901801b2013-10-06 23:55:51 -07006426 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006427}
Johan Hedberga88a9652011-03-30 13:18:12 +03006428
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006429void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6430 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006431{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006432 struct mgmt_ev_device_found *ev;
6433 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6434 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006435
Johan Hedbergb644ba32012-01-17 21:48:47 +02006436 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006437
Johan Hedbergb644ba32012-01-17 21:48:47 +02006438 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006439
Johan Hedbergb644ba32012-01-17 21:48:47 +02006440 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006441 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006442 ev->rssi = rssi;
6443
6444 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006445 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006446
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006447 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006448
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006449 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006450}
Johan Hedberg314b2382011-04-27 10:29:57 -04006451
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006452void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006453{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006454 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006455 struct pending_cmd *cmd;
6456
Andre Guedes343fb142011-11-22 17:14:19 -03006457 BT_DBG("%s discovering %u", hdev->name, discovering);
6458
Johan Hedberg164a6e72011-11-01 17:06:44 +02006459 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006460 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006461 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006462 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006463
6464 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006465 u8 type = hdev->discovery.type;
6466
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006467 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6468 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006469 mgmt_pending_remove(cmd);
6470 }
6471
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006472 memset(&ev, 0, sizeof(ev));
6473 ev.type = hdev->discovery.type;
6474 ev.discovering = discovering;
6475
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006476 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006477}
Antti Julku5e762442011-08-25 16:48:02 +03006478
Marcel Holtmann5976e602013-10-06 04:08:14 -07006479static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6480{
6481 BT_DBG("%s status %u", hdev->name, status);
6482
6483 /* Clear the advertising mgmt setting if we failed to re-enable it */
6484 if (status) {
6485 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006486 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006487 }
6488}
6489
6490void mgmt_reenable_advertising(struct hci_dev *hdev)
6491{
6492 struct hci_request req;
6493
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006494 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006495 return;
6496
6497 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6498 return;
6499
6500 hci_req_init(&req, hdev);
6501 enable_advertising(&req);
6502
6503 /* If this fails we have no option but to let user space know
6504 * that we've disabled advertising.
6505 */
6506 if (hci_req_run(&req, adv_enable_complete) < 0) {
6507 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006508 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006509 }
6510}