blob: ab70d5858db9932819afcb9b94ad45783bef907e [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,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200121 MGMT_EV_UNCONF_INDEX_ADDED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200122};
123
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800124#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200125
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200126#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
127 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
128
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200129struct pending_cmd {
130 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200131 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200132 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100133 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200134 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300135 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136};
137
Johan Hedbergca69b792011-11-11 18:10:00 +0200138/* HCI to MGMT error code conversion table */
139static u8 mgmt_status_table[] = {
140 MGMT_STATUS_SUCCESS,
141 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
142 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
143 MGMT_STATUS_FAILED, /* Hardware Failure */
144 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
145 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200146 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200147 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
148 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
149 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
150 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
151 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
152 MGMT_STATUS_BUSY, /* Command Disallowed */
153 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
154 MGMT_STATUS_REJECTED, /* Rejected Security */
155 MGMT_STATUS_REJECTED, /* Rejected Personal */
156 MGMT_STATUS_TIMEOUT, /* Host Timeout */
157 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
158 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
159 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
160 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
161 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
162 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
163 MGMT_STATUS_BUSY, /* Repeated Attempts */
164 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
165 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
166 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
167 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
168 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
169 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
170 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
171 MGMT_STATUS_FAILED, /* Unspecified Error */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
173 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
174 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
175 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
176 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
177 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
178 MGMT_STATUS_FAILED, /* Unit Link Key Used */
179 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
180 MGMT_STATUS_TIMEOUT, /* Instant Passed */
181 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
182 MGMT_STATUS_FAILED, /* Transaction Collision */
183 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
184 MGMT_STATUS_REJECTED, /* QoS Rejected */
185 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
186 MGMT_STATUS_REJECTED, /* Insufficient Security */
187 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
188 MGMT_STATUS_BUSY, /* Role Switch Pending */
189 MGMT_STATUS_FAILED, /* Slot Violation */
190 MGMT_STATUS_FAILED, /* Role Switch Failed */
191 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
192 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
193 MGMT_STATUS_BUSY, /* Host Busy Pairing */
194 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
195 MGMT_STATUS_BUSY, /* Controller Busy */
196 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
197 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
198 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
199 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
200 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
201};
202
203static u8 mgmt_status(u8 hci_status)
204{
205 if (hci_status < ARRAY_SIZE(mgmt_status_table))
206 return mgmt_status_table[hci_status];
207
208 return MGMT_STATUS_FAILED;
209}
210
Szymon Janc4e51eae2011-02-25 19:05:48 +0100211static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200212{
213 struct sk_buff *skb;
214 struct mgmt_hdr *hdr;
215 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300216 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200217
Szymon Janc34eb5252011-02-28 14:10:08 +0100218 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200219
Andre Guedes790eff42012-06-07 19:05:46 -0300220 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200221 if (!skb)
222 return -ENOMEM;
223
224 hdr = (void *) skb_put(skb, sizeof(*hdr));
225
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700226 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100227 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228 hdr->len = cpu_to_le16(sizeof(*ev));
229
230 ev = (void *) skb_put(skb, sizeof(*ev));
231 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200232 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200233
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300234 err = sock_queue_rcv_skb(sk, skb);
235 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200236 kfree_skb(skb);
237
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300238 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200239}
240
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200241static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300242 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200243{
244 struct sk_buff *skb;
245 struct mgmt_hdr *hdr;
246 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300247 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200248
249 BT_DBG("sock %p", sk);
250
Andre Guedes790eff42012-06-07 19:05:46 -0300251 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200252 if (!skb)
253 return -ENOMEM;
254
255 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200256
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700257 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100258 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200259 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200260
Johan Hedberga38528f2011-01-22 06:46:43 +0200261 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200262 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200263 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100264
265 if (rp)
266 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200267
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300268 err = sock_queue_rcv_skb(sk, skb);
269 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200270 kfree_skb(skb);
271
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100272 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200273}
274
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300275static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
276 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200277{
278 struct mgmt_rp_read_version rp;
279
280 BT_DBG("sock %p", sk);
281
282 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700283 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200284
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200285 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300286 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200287}
288
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300289static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
290 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200291{
292 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200293 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
294 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200295 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200296 size_t rp_size;
297 int i, err;
298
299 BT_DBG("sock %p", sk);
300
301 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
302
303 rp = kmalloc(rp_size, GFP_KERNEL);
304 if (!rp)
305 return -ENOMEM;
306
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700307 rp->num_commands = cpu_to_le16(num_commands);
308 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200309
310 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
311 put_unaligned_le16(mgmt_commands[i], opcode);
312
313 for (i = 0; i < num_events; i++, opcode++)
314 put_unaligned_le16(mgmt_events[i], opcode);
315
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200316 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300317 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200318 kfree(rp);
319
320 return err;
321}
322
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300323static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
324 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200325{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200326 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200327 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200328 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200329 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300330 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200331
332 BT_DBG("sock %p", sk);
333
334 read_lock(&hci_dev_list_lock);
335
336 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300337 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700338 if (d->dev_type == HCI_BREDR)
339 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340 }
341
Johan Hedberga38528f2011-01-22 06:46:43 +0200342 rp_len = sizeof(*rp) + (2 * count);
343 rp = kmalloc(rp_len, GFP_ATOMIC);
344 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100345 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200346 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100347 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200348
Johan Hedberg476e44c2012-10-19 20:10:46 +0300349 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200350 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200351 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200352 continue;
353
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700354 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
355 continue;
356
Marcel Holtmann4a964402014-07-02 19:10:33 +0200357 if (test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmannfee746b2014-06-29 12:13:05 +0200358 continue;
359
Marcel Holtmann1514b892013-10-06 08:25:01 -0700360 if (d->dev_type == HCI_BREDR) {
361 rp->index[count++] = cpu_to_le16(d->id);
362 BT_DBG("Added hci%u", d->id);
363 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200364 }
365
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 rp->num_controllers = cpu_to_le16(count);
367 rp_len = sizeof(*rp) + (2 * count);
368
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200369 read_unlock(&hci_dev_list_lock);
370
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200371 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300372 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200373
Johan Hedberga38528f2011-01-22 06:46:43 +0200374 kfree(rp);
375
376 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377}
378
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200379static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200380{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200382
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200383 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200384 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800385 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200386
Andre Guedesed3fa312012-07-24 15:03:46 -0300387 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300388 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500389 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
390 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300391 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200392 settings |= MGMT_SETTING_BREDR;
393 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700394
395 if (lmp_ssp_capable(hdev)) {
396 settings |= MGMT_SETTING_SSP;
397 settings |= MGMT_SETTING_HS;
398 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800399
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800400 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200401 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800402 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700403 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100404
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300405 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200406 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300407 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200408 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300409 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200410
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411 return settings;
412}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200413
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200414static u32 get_current_settings(struct hci_dev *hdev)
415{
416 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200417
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200418 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100419 settings |= MGMT_SETTING_POWERED;
420
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200421 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200422 settings |= MGMT_SETTING_CONNECTABLE;
423
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500424 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
425 settings |= MGMT_SETTING_FAST_CONNECTABLE;
426
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200427 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200428 settings |= MGMT_SETTING_DISCOVERABLE;
429
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200430 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200431 settings |= MGMT_SETTING_PAIRABLE;
432
Johan Hedberg56f87902013-10-02 13:43:13 +0300433 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200434 settings |= MGMT_SETTING_BREDR;
435
Johan Hedberg06199cf2012-02-22 16:37:11 +0200436 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200437 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200438
Johan Hedberg47990ea2012-02-22 11:58:37 +0200439 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200440 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200441
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200442 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200443 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200444
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200445 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
446 settings |= MGMT_SETTING_HS;
447
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200448 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300449 settings |= MGMT_SETTING_ADVERTISING;
450
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800451 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
452 settings |= MGMT_SETTING_SECURE_CONN;
453
Johan Hedberg0663b292014-06-24 13:15:50 +0300454 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800455 settings |= MGMT_SETTING_DEBUG_KEYS;
456
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200457 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
458 settings |= MGMT_SETTING_PRIVACY;
459
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200460 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200461}
462
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300463#define PNP_INFO_SVCLASS_ID 0x1200
464
Johan Hedberg213202e2013-01-27 00:31:33 +0200465static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
466{
467 u8 *ptr = data, *uuids_start = NULL;
468 struct bt_uuid *uuid;
469
470 if (len < 4)
471 return ptr;
472
473 list_for_each_entry(uuid, &hdev->uuids, list) {
474 u16 uuid16;
475
476 if (uuid->size != 16)
477 continue;
478
479 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
480 if (uuid16 < 0x1100)
481 continue;
482
483 if (uuid16 == PNP_INFO_SVCLASS_ID)
484 continue;
485
486 if (!uuids_start) {
487 uuids_start = ptr;
488 uuids_start[0] = 1;
489 uuids_start[1] = EIR_UUID16_ALL;
490 ptr += 2;
491 }
492
493 /* Stop if not enough space to put next UUID */
494 if ((ptr - data) + sizeof(u16) > len) {
495 uuids_start[1] = EIR_UUID16_SOME;
496 break;
497 }
498
499 *ptr++ = (uuid16 & 0x00ff);
500 *ptr++ = (uuid16 & 0xff00) >> 8;
501 uuids_start[0] += sizeof(uuid16);
502 }
503
504 return ptr;
505}
506
Johan Hedbergcdf19632013-01-27 00:31:34 +0200507static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
508{
509 u8 *ptr = data, *uuids_start = NULL;
510 struct bt_uuid *uuid;
511
512 if (len < 6)
513 return ptr;
514
515 list_for_each_entry(uuid, &hdev->uuids, list) {
516 if (uuid->size != 32)
517 continue;
518
519 if (!uuids_start) {
520 uuids_start = ptr;
521 uuids_start[0] = 1;
522 uuids_start[1] = EIR_UUID32_ALL;
523 ptr += 2;
524 }
525
526 /* Stop if not enough space to put next UUID */
527 if ((ptr - data) + sizeof(u32) > len) {
528 uuids_start[1] = EIR_UUID32_SOME;
529 break;
530 }
531
532 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
533 ptr += sizeof(u32);
534 uuids_start[0] += sizeof(u32);
535 }
536
537 return ptr;
538}
539
Johan Hedbergc00d5752013-01-27 00:31:35 +0200540static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
541{
542 u8 *ptr = data, *uuids_start = NULL;
543 struct bt_uuid *uuid;
544
545 if (len < 18)
546 return ptr;
547
548 list_for_each_entry(uuid, &hdev->uuids, list) {
549 if (uuid->size != 128)
550 continue;
551
552 if (!uuids_start) {
553 uuids_start = ptr;
554 uuids_start[0] = 1;
555 uuids_start[1] = EIR_UUID128_ALL;
556 ptr += 2;
557 }
558
559 /* Stop if not enough space to put next UUID */
560 if ((ptr - data) + 16 > len) {
561 uuids_start[1] = EIR_UUID128_SOME;
562 break;
563 }
564
565 memcpy(ptr, uuid->uuid, 16);
566 ptr += 16;
567 uuids_start[0] += 16;
568 }
569
570 return ptr;
571}
572
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300573static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
574{
575 struct pending_cmd *cmd;
576
577 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
578 if (cmd->opcode == opcode)
579 return cmd;
580 }
581
582 return NULL;
583}
584
Johan Hedberg95868422014-06-28 17:54:07 +0300585static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
586 struct hci_dev *hdev,
587 const void *data)
588{
589 struct pending_cmd *cmd;
590
591 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
592 if (cmd->user_data != data)
593 continue;
594 if (cmd->opcode == opcode)
595 return cmd;
596 }
597
598 return NULL;
599}
600
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700601static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
602{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700603 u8 ad_len = 0;
604 size_t name_len;
605
606 name_len = strlen(hdev->dev_name);
607 if (name_len > 0) {
608 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
609
610 if (name_len > max_len) {
611 name_len = max_len;
612 ptr[1] = EIR_NAME_SHORT;
613 } else
614 ptr[1] = EIR_NAME_COMPLETE;
615
616 ptr[0] = name_len + 1;
617
618 memcpy(ptr + 2, hdev->dev_name, name_len);
619
620 ad_len += (name_len + 2);
621 ptr += (name_len + 2);
622 }
623
624 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700625}
626
627static void update_scan_rsp_data(struct hci_request *req)
628{
629 struct hci_dev *hdev = req->hdev;
630 struct hci_cp_le_set_scan_rsp_data cp;
631 u8 len;
632
Johan Hedberg7751ef12013-10-19 23:38:15 +0300633 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700634 return;
635
636 memset(&cp, 0, sizeof(cp));
637
638 len = create_scan_rsp_data(hdev, cp.data);
639
Johan Hedbergeb438b52013-10-16 15:31:07 +0300640 if (hdev->scan_rsp_data_len == len &&
641 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700642 return;
643
Johan Hedbergeb438b52013-10-16 15:31:07 +0300644 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
645 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700646
647 cp.length = len;
648
649 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
650}
651
Johan Hedberg9a43e252013-10-20 19:00:07 +0300652static u8 get_adv_discov_flags(struct hci_dev *hdev)
653{
654 struct pending_cmd *cmd;
655
656 /* If there's a pending mgmt command the flags will not yet have
657 * their final values, so check for this first.
658 */
659 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
660 if (cmd) {
661 struct mgmt_mode *cp = cmd->param;
662 if (cp->val == 0x01)
663 return LE_AD_GENERAL;
664 else if (cp->val == 0x02)
665 return LE_AD_LIMITED;
666 } else {
667 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
668 return LE_AD_LIMITED;
669 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
670 return LE_AD_GENERAL;
671 }
672
673 return 0;
674}
675
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700676static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700677{
678 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700679
Johan Hedberg9a43e252013-10-20 19:00:07 +0300680 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700681
Johan Hedberge8340042014-01-30 11:16:50 -0800682 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700683 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700684
685 if (flags) {
686 BT_DBG("adv flags 0x%02x", flags);
687
688 ptr[0] = 2;
689 ptr[1] = EIR_FLAGS;
690 ptr[2] = flags;
691
692 ad_len += 3;
693 ptr += 3;
694 }
695
696 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
697 ptr[0] = 2;
698 ptr[1] = EIR_TX_POWER;
699 ptr[2] = (u8) hdev->adv_tx_power;
700
701 ad_len += 3;
702 ptr += 3;
703 }
704
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700705 return ad_len;
706}
707
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700708static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700709{
710 struct hci_dev *hdev = req->hdev;
711 struct hci_cp_le_set_adv_data cp;
712 u8 len;
713
Johan Hedberg10994ce2013-10-19 23:38:16 +0300714 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700715 return;
716
717 memset(&cp, 0, sizeof(cp));
718
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700719 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700720
721 if (hdev->adv_data_len == len &&
722 memcmp(cp.data, hdev->adv_data, len) == 0)
723 return;
724
725 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
726 hdev->adv_data_len = len;
727
728 cp.length = len;
729
730 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
731}
732
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300733static void create_eir(struct hci_dev *hdev, u8 *data)
734{
735 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300736 size_t name_len;
737
738 name_len = strlen(hdev->dev_name);
739
740 if (name_len > 0) {
741 /* EIR Data type */
742 if (name_len > 48) {
743 name_len = 48;
744 ptr[1] = EIR_NAME_SHORT;
745 } else
746 ptr[1] = EIR_NAME_COMPLETE;
747
748 /* EIR Data length */
749 ptr[0] = name_len + 1;
750
751 memcpy(ptr + 2, hdev->dev_name, name_len);
752
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300753 ptr += (name_len + 2);
754 }
755
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100756 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700757 ptr[0] = 2;
758 ptr[1] = EIR_TX_POWER;
759 ptr[2] = (u8) hdev->inq_tx_power;
760
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700761 ptr += 3;
762 }
763
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700764 if (hdev->devid_source > 0) {
765 ptr[0] = 9;
766 ptr[1] = EIR_DEVICE_ID;
767
768 put_unaligned_le16(hdev->devid_source, ptr + 2);
769 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
770 put_unaligned_le16(hdev->devid_product, ptr + 6);
771 put_unaligned_le16(hdev->devid_version, ptr + 8);
772
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700773 ptr += 10;
774 }
775
Johan Hedberg213202e2013-01-27 00:31:33 +0200776 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200777 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200778 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300779}
780
Johan Hedberg890ea892013-03-15 17:06:52 -0500781static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300782{
Johan Hedberg890ea892013-03-15 17:06:52 -0500783 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300784 struct hci_cp_write_eir cp;
785
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200786 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500787 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200788
Johan Hedberg976eb202012-10-24 21:12:01 +0300789 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500790 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300791
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200792 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500793 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300794
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200795 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300797
798 memset(&cp, 0, sizeof(cp));
799
800 create_eir(hdev, cp.data);
801
802 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500803 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300804
805 memcpy(hdev->eir, cp.data, sizeof(cp.data));
806
Johan Hedberg890ea892013-03-15 17:06:52 -0500807 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300808}
809
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200810static u8 get_service_classes(struct hci_dev *hdev)
811{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300812 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200813 u8 val = 0;
814
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300815 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200816 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817
818 return val;
819}
820
Johan Hedberg890ea892013-03-15 17:06:52 -0500821static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200822{
Johan Hedberg890ea892013-03-15 17:06:52 -0500823 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200824 u8 cod[3];
825
826 BT_DBG("%s", hdev->name);
827
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200828 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500829 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200830
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300831 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
832 return;
833
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200834 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500835 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200836
837 cod[0] = hdev->minor_class;
838 cod[1] = hdev->major_class;
839 cod[2] = get_service_classes(hdev);
840
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700841 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
842 cod[1] |= 0x20;
843
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200844 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500845 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200846
Johan Hedberg890ea892013-03-15 17:06:52 -0500847 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200848}
849
Johan Hedberga4858cb2014-02-25 19:56:31 +0200850static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200851{
852 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200853
854 /* If there's a pending mgmt command the flag will not yet have
855 * it's final value, so check for this first.
856 */
857 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
858 if (cmd) {
859 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200860 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200861 }
862
Johan Hedberga4858cb2014-02-25 19:56:31 +0200863 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200864}
865
866static void enable_advertising(struct hci_request *req)
867{
868 struct hci_dev *hdev = req->hdev;
869 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200870 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200871 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200872
Johan Hedberg8d972502014-02-28 12:54:14 +0200873 /* Clear the HCI_ADVERTISING bit temporarily so that the
874 * hci_update_random_address knows that it's safe to go ahead
875 * and write a new random address. The flag will be set back on
876 * as soon as the SET_ADV_ENABLE HCI command completes.
877 */
878 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
879
Johan Hedberga4858cb2014-02-25 19:56:31 +0200880 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200881
Johan Hedberga4858cb2014-02-25 19:56:31 +0200882 /* Set require_privacy to true only when non-connectable
883 * advertising is used. In that case it is fine to use a
884 * non-resolvable private address.
885 */
886 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200887 return;
888
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800889 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700890 cp.min_interval = cpu_to_le16(0x0800);
891 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200892 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200893 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200894 cp.channel_map = hdev->le_adv_channel_map;
895
896 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
897
898 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
899}
900
901static void disable_advertising(struct hci_request *req)
902{
903 u8 enable = 0x00;
904
905 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
906}
907
Johan Hedberg7d785252011-12-15 00:47:39 +0200908static void service_cache_off(struct work_struct *work)
909{
910 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300911 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500912 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200913
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200914 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200915 return;
916
Johan Hedberg890ea892013-03-15 17:06:52 -0500917 hci_req_init(&req, hdev);
918
Johan Hedberg7d785252011-12-15 00:47:39 +0200919 hci_dev_lock(hdev);
920
Johan Hedberg890ea892013-03-15 17:06:52 -0500921 update_eir(&req);
922 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200923
924 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500925
926 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200927}
928
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200929static void rpa_expired(struct work_struct *work)
930{
931 struct hci_dev *hdev = container_of(work, struct hci_dev,
932 rpa_expired.work);
933 struct hci_request req;
934
935 BT_DBG("");
936
937 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
938
939 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
940 hci_conn_num(hdev, LE_LINK) > 0)
941 return;
942
943 /* The generation of a new RPA and programming it into the
944 * controller happens in the enable_advertising() function.
945 */
946
947 hci_req_init(&req, hdev);
948
949 disable_advertising(&req);
950 enable_advertising(&req);
951
952 hci_req_run(&req, NULL);
953}
954
Johan Hedberg6a919082012-02-28 06:17:26 +0200955static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200956{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200957 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200958 return;
959
Johan Hedberg4f87da82012-03-02 19:55:56 +0200960 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200961 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200962
Johan Hedberg4f87da82012-03-02 19:55:56 +0200963 /* Non-mgmt controlled devices get this bit set
964 * implicitly so that pairing works for them, however
965 * for mgmt we require user-space to explicitly enable
966 * it
967 */
968 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200969}
970
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200971static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300972 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200973{
974 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200975
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200976 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200977
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300978 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200979
Johan Hedberg03811012010-12-08 00:21:06 +0200980 memset(&rp, 0, sizeof(rp));
981
Johan Hedberg03811012010-12-08 00:21:06 +0200982 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200983
984 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200985 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200986
987 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
988 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
989
990 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200991
992 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200993 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200994
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300995 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200996
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200997 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300998 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200999}
1000
1001static void mgmt_pending_free(struct pending_cmd *cmd)
1002{
1003 sock_put(cmd->sk);
1004 kfree(cmd->param);
1005 kfree(cmd);
1006}
1007
1008static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001009 struct hci_dev *hdev, void *data,
1010 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001011{
1012 struct pending_cmd *cmd;
1013
Johan Hedbergfca20012014-06-28 17:54:05 +03001014 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001015 if (!cmd)
1016 return NULL;
1017
1018 cmd->opcode = opcode;
1019 cmd->index = hdev->id;
1020
Andre Guedes12b94562012-06-07 19:05:45 -03001021 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001022 if (!cmd->param) {
1023 kfree(cmd);
1024 return NULL;
1025 }
1026
1027 if (data)
1028 memcpy(cmd->param, data, len);
1029
1030 cmd->sk = sk;
1031 sock_hold(sk);
1032
1033 list_add(&cmd->list, &hdev->mgmt_pending);
1034
1035 return cmd;
1036}
1037
1038static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001039 void (*cb)(struct pending_cmd *cmd,
1040 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001041 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001042{
Andre Guedesa3d09352013-02-01 11:21:30 -03001043 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001044
Andre Guedesa3d09352013-02-01 11:21:30 -03001045 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001046 if (opcode > 0 && cmd->opcode != opcode)
1047 continue;
1048
1049 cb(cmd, data);
1050 }
1051}
1052
Johan Hedberg03811012010-12-08 00:21:06 +02001053static void mgmt_pending_remove(struct pending_cmd *cmd)
1054{
1055 list_del(&cmd->list);
1056 mgmt_pending_free(cmd);
1057}
1058
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001059static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001060{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001061 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001062
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001063 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001064 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001065}
1066
Johan Hedberg8b064a32014-02-24 14:52:22 +02001067static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1068{
1069 BT_DBG("%s status 0x%02x", hdev->name, status);
1070
Johan Hedberga3172b72014-02-28 09:33:44 +02001071 if (hci_conn_count(hdev) == 0) {
1072 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001073 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001074 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001075}
1076
Johan Hedberg21a60d32014-06-10 14:05:58 +03001077static void hci_stop_discovery(struct hci_request *req)
1078{
1079 struct hci_dev *hdev = req->hdev;
1080 struct hci_cp_remote_name_req_cancel cp;
1081 struct inquiry_entry *e;
1082
1083 switch (hdev->discovery.state) {
1084 case DISCOVERY_FINDING:
1085 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1086 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1087 } else {
1088 cancel_delayed_work(&hdev->le_scan_disable);
1089 hci_req_add_le_scan_disable(req);
1090 }
1091
1092 break;
1093
1094 case DISCOVERY_RESOLVING:
1095 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1096 NAME_PENDING);
1097 if (!e)
1098 return;
1099
1100 bacpy(&cp.bdaddr, &e->data.bdaddr);
1101 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1102 &cp);
1103
1104 break;
1105
1106 default:
1107 /* Passive scanning */
1108 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1109 hci_req_add_le_scan_disable(req);
1110 break;
1111 }
1112}
1113
Johan Hedberg8b064a32014-02-24 14:52:22 +02001114static int clean_up_hci_state(struct hci_dev *hdev)
1115{
1116 struct hci_request req;
1117 struct hci_conn *conn;
1118
1119 hci_req_init(&req, hdev);
1120
1121 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1122 test_bit(HCI_PSCAN, &hdev->flags)) {
1123 u8 scan = 0x00;
1124 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1125 }
1126
1127 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1128 disable_advertising(&req);
1129
Johan Hedbergf8680f12014-06-10 14:05:59 +03001130 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001131
1132 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1133 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001134 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001135
Johan Hedbergc9910d02014-02-27 14:35:12 +02001136 switch (conn->state) {
1137 case BT_CONNECTED:
1138 case BT_CONFIG:
1139 dc.handle = cpu_to_le16(conn->handle);
1140 dc.reason = 0x15; /* Terminated due to Power Off */
1141 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1142 break;
1143 case BT_CONNECT:
1144 if (conn->type == LE_LINK)
1145 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1146 0, NULL);
1147 else if (conn->type == ACL_LINK)
1148 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1149 6, &conn->dst);
1150 break;
1151 case BT_CONNECT2:
1152 bacpy(&rej.bdaddr, &conn->dst);
1153 rej.reason = 0x15; /* Terminated due to Power Off */
1154 if (conn->type == ACL_LINK)
1155 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1156 sizeof(rej), &rej);
1157 else if (conn->type == SCO_LINK)
1158 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1159 sizeof(rej), &rej);
1160 break;
1161 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001162 }
1163
1164 return hci_req_run(&req, clean_up_hci_complete);
1165}
1166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001167static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001168 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001169{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001170 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001171 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001172 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001174 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001175
Johan Hedberga7e80f22013-01-09 16:05:19 +02001176 if (cp->val != 0x00 && cp->val != 0x01)
1177 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1178 MGMT_STATUS_INVALID_PARAMS);
1179
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001180 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001181
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001182 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1183 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1184 MGMT_STATUS_BUSY);
1185 goto failed;
1186 }
1187
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001188 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1189 cancel_delayed_work(&hdev->power_off);
1190
1191 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001192 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1193 data, len);
1194 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001195 goto failed;
1196 }
1197 }
1198
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001199 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001200 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001201 goto failed;
1202 }
1203
Johan Hedberg03811012010-12-08 00:21:06 +02001204 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1205 if (!cmd) {
1206 err = -ENOMEM;
1207 goto failed;
1208 }
1209
Johan Hedberg8b064a32014-02-24 14:52:22 +02001210 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001211 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001212 err = 0;
1213 } else {
1214 /* Disconnect connections, stop scans, etc */
1215 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001216 if (!err)
1217 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1218 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001219
Johan Hedberg8b064a32014-02-24 14:52:22 +02001220 /* ENODATA means there were no HCI commands queued */
1221 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001222 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001223 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1224 err = 0;
1225 }
1226 }
Johan Hedberg03811012010-12-08 00:21:06 +02001227
1228failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001229 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001230 return err;
1231}
1232
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001233static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1234 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001235{
1236 struct sk_buff *skb;
1237 struct mgmt_hdr *hdr;
1238
Andre Guedes790eff42012-06-07 19:05:46 -03001239 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001240 if (!skb)
1241 return -ENOMEM;
1242
1243 hdr = (void *) skb_put(skb, sizeof(*hdr));
1244 hdr->opcode = cpu_to_le16(event);
1245 if (hdev)
1246 hdr->index = cpu_to_le16(hdev->id);
1247 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001248 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001249 hdr->len = cpu_to_le16(data_len);
1250
1251 if (data)
1252 memcpy(skb_put(skb, data_len), data, data_len);
1253
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001254 /* Time stamp */
1255 __net_timestamp(skb);
1256
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001257 hci_send_to_control(skb, skip_sk);
1258 kfree_skb(skb);
1259
1260 return 0;
1261}
1262
1263static int new_settings(struct hci_dev *hdev, struct sock *skip)
1264{
1265 __le32 ev;
1266
1267 ev = cpu_to_le32(get_current_settings(hdev));
1268
1269 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1270}
1271
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001272struct cmd_lookup {
1273 struct sock *sk;
1274 struct hci_dev *hdev;
1275 u8 mgmt_status;
1276};
1277
1278static void settings_rsp(struct pending_cmd *cmd, void *data)
1279{
1280 struct cmd_lookup *match = data;
1281
1282 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1283
1284 list_del(&cmd->list);
1285
1286 if (match->sk == NULL) {
1287 match->sk = cmd->sk;
1288 sock_hold(match->sk);
1289 }
1290
1291 mgmt_pending_free(cmd);
1292}
1293
1294static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1295{
1296 u8 *status = data;
1297
1298 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1299 mgmt_pending_remove(cmd);
1300}
1301
Johan Hedberge6fe7982013-10-02 15:45:22 +03001302static u8 mgmt_bredr_support(struct hci_dev *hdev)
1303{
1304 if (!lmp_bredr_capable(hdev))
1305 return MGMT_STATUS_NOT_SUPPORTED;
1306 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1307 return MGMT_STATUS_REJECTED;
1308 else
1309 return MGMT_STATUS_SUCCESS;
1310}
1311
1312static u8 mgmt_le_support(struct hci_dev *hdev)
1313{
1314 if (!lmp_le_capable(hdev))
1315 return MGMT_STATUS_NOT_SUPPORTED;
1316 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1317 return MGMT_STATUS_REJECTED;
1318 else
1319 return MGMT_STATUS_SUCCESS;
1320}
1321
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001322static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1323{
1324 struct pending_cmd *cmd;
1325 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001326 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001327 bool changed;
1328
1329 BT_DBG("status 0x%02x", status);
1330
1331 hci_dev_lock(hdev);
1332
1333 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1334 if (!cmd)
1335 goto unlock;
1336
1337 if (status) {
1338 u8 mgmt_err = mgmt_status(status);
1339 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001340 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001341 goto remove_cmd;
1342 }
1343
1344 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001345 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001346 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1347 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001348
1349 if (hdev->discov_timeout > 0) {
1350 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1351 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1352 to);
1353 }
1354 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001355 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1356 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001357 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001358
1359 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1360
1361 if (changed)
1362 new_settings(hdev, cmd->sk);
1363
Marcel Holtmann970ba522013-10-15 06:33:57 -07001364 /* When the discoverable mode gets changed, make sure
1365 * that class of device has the limited discoverable
1366 * bit correctly set.
1367 */
1368 hci_req_init(&req, hdev);
1369 update_class(&req);
1370 hci_req_run(&req, NULL);
1371
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001372remove_cmd:
1373 mgmt_pending_remove(cmd);
1374
1375unlock:
1376 hci_dev_unlock(hdev);
1377}
1378
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001379static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001380 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001381{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001382 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001383 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001384 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001385 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001386 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001387 int err;
1388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001389 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001390
Johan Hedberg9a43e252013-10-20 19:00:07 +03001391 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1392 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001393 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001394 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001395
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001396 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001397 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1398 MGMT_STATUS_INVALID_PARAMS);
1399
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001400 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001401
1402 /* Disabling discoverable requires that no timeout is set,
1403 * and enabling limited discoverable requires a timeout.
1404 */
1405 if ((cp->val == 0x00 && timeout > 0) ||
1406 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001407 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001408 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001409
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001410 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001411
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001412 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001413 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001414 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001415 goto failed;
1416 }
1417
1418 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001419 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001420 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001421 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001422 goto failed;
1423 }
1424
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001425 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001426 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001427 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001428 goto failed;
1429 }
1430
1431 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001432 bool changed = false;
1433
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001434 /* Setting limited discoverable when powered off is
1435 * not a valid operation since it requires a timeout
1436 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1437 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001438 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1439 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1440 changed = true;
1441 }
1442
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001443 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001444 if (err < 0)
1445 goto failed;
1446
1447 if (changed)
1448 err = new_settings(hdev, sk);
1449
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001450 goto failed;
1451 }
1452
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001453 /* If the current mode is the same, then just update the timeout
1454 * value with the new value. And if only the timeout gets updated,
1455 * then no need for any HCI transactions.
1456 */
1457 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1458 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1459 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001460 cancel_delayed_work(&hdev->discov_off);
1461 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001462
Marcel Holtmann36261542013-10-15 08:28:51 -07001463 if (cp->val && hdev->discov_timeout > 0) {
1464 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001465 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001466 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001467 }
1468
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001469 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001470 goto failed;
1471 }
1472
1473 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1474 if (!cmd) {
1475 err = -ENOMEM;
1476 goto failed;
1477 }
1478
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001479 /* Cancel any potential discoverable timeout that might be
1480 * still active and store new timeout value. The arming of
1481 * the timeout happens in the complete handler.
1482 */
1483 cancel_delayed_work(&hdev->discov_off);
1484 hdev->discov_timeout = timeout;
1485
Johan Hedbergb456f872013-10-19 23:38:22 +03001486 /* Limited discoverable mode */
1487 if (cp->val == 0x02)
1488 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1489 else
1490 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1491
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001492 hci_req_init(&req, hdev);
1493
Johan Hedberg9a43e252013-10-20 19:00:07 +03001494 /* The procedure for LE-only controllers is much simpler - just
1495 * update the advertising data.
1496 */
1497 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1498 goto update_ad;
1499
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001500 scan = SCAN_PAGE;
1501
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001502 if (cp->val) {
1503 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001504
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001505 if (cp->val == 0x02) {
1506 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001507 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001508 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1509 hci_cp.iac_lap[1] = 0x8b;
1510 hci_cp.iac_lap[2] = 0x9e;
1511 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1512 hci_cp.iac_lap[4] = 0x8b;
1513 hci_cp.iac_lap[5] = 0x9e;
1514 } else {
1515 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001516 hci_cp.num_iac = 1;
1517 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1518 hci_cp.iac_lap[1] = 0x8b;
1519 hci_cp.iac_lap[2] = 0x9e;
1520 }
1521
1522 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1523 (hci_cp.num_iac * 3) + 1, &hci_cp);
1524
1525 scan |= SCAN_INQUIRY;
1526 } else {
1527 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1528 }
1529
1530 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001531
Johan Hedberg9a43e252013-10-20 19:00:07 +03001532update_ad:
1533 update_adv_data(&req);
1534
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001535 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001536 if (err < 0)
1537 mgmt_pending_remove(cmd);
1538
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001539failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001540 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001541 return err;
1542}
1543
Johan Hedberg406d7802013-03-15 17:07:09 -05001544static void write_fast_connectable(struct hci_request *req, bool enable)
1545{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001546 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001547 struct hci_cp_write_page_scan_activity acp;
1548 u8 type;
1549
Johan Hedberg547003b2013-10-21 16:51:53 +03001550 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1551 return;
1552
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001553 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1554 return;
1555
Johan Hedberg406d7802013-03-15 17:07:09 -05001556 if (enable) {
1557 type = PAGE_SCAN_TYPE_INTERLACED;
1558
1559 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001560 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001561 } else {
1562 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1563
1564 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001565 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001566 }
1567
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001568 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001569
Johan Hedbergbd98b992013-03-15 17:07:13 -05001570 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1571 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1572 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1573 sizeof(acp), &acp);
1574
1575 if (hdev->page_scan_type != type)
1576 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001577}
1578
Johan Hedberg2b76f452013-03-15 17:07:04 -05001579static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1580{
1581 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001582 struct mgmt_mode *cp;
1583 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001584
1585 BT_DBG("status 0x%02x", status);
1586
1587 hci_dev_lock(hdev);
1588
1589 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1590 if (!cmd)
1591 goto unlock;
1592
Johan Hedberg37438c12013-10-14 16:20:05 +03001593 if (status) {
1594 u8 mgmt_err = mgmt_status(status);
1595 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1596 goto remove_cmd;
1597 }
1598
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001599 cp = cmd->param;
1600 if (cp->val)
1601 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1602 else
1603 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1604
Johan Hedberg2b76f452013-03-15 17:07:04 -05001605 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1606
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001607 if (changed)
1608 new_settings(hdev, cmd->sk);
1609
Johan Hedberg37438c12013-10-14 16:20:05 +03001610remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001611 mgmt_pending_remove(cmd);
1612
1613unlock:
1614 hci_dev_unlock(hdev);
1615}
1616
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001617static int set_connectable_update_settings(struct hci_dev *hdev,
1618 struct sock *sk, u8 val)
1619{
1620 bool changed = false;
1621 int err;
1622
1623 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1624 changed = true;
1625
1626 if (val) {
1627 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1628 } else {
1629 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1630 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1631 }
1632
1633 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1634 if (err < 0)
1635 return err;
1636
1637 if (changed)
1638 return new_settings(hdev, sk);
1639
1640 return 0;
1641}
1642
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001643static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001644 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001645{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001646 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001647 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001648 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001649 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001650 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001652 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001653
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001654 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1655 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001656 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001657 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001658
Johan Hedberga7e80f22013-01-09 16:05:19 +02001659 if (cp->val != 0x00 && cp->val != 0x01)
1660 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1661 MGMT_STATUS_INVALID_PARAMS);
1662
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001663 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001664
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001665 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001666 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001667 goto failed;
1668 }
1669
1670 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001671 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001672 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001673 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001674 goto failed;
1675 }
1676
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001677 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1678 if (!cmd) {
1679 err = -ENOMEM;
1680 goto failed;
1681 }
1682
Johan Hedberg2b76f452013-03-15 17:07:04 -05001683 hci_req_init(&req, hdev);
1684
Johan Hedberg9a43e252013-10-20 19:00:07 +03001685 /* If BR/EDR is not enabled and we disable advertising as a
1686 * by-product of disabling connectable, we need to update the
1687 * advertising flags.
1688 */
1689 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1690 if (!cp->val) {
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1693 }
1694 update_adv_data(&req);
1695 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001696 if (cp->val) {
1697 scan = SCAN_PAGE;
1698 } else {
1699 scan = 0;
1700
1701 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001702 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001703 cancel_delayed_work(&hdev->discov_off);
1704 }
1705
1706 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1707 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001708
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001709 /* If we're going from non-connectable to connectable or
1710 * vice-versa when fast connectable is enabled ensure that fast
1711 * connectable gets disabled. write_fast_connectable won't do
1712 * anything if the page scan parameters are already what they
1713 * should be.
1714 */
1715 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001716 write_fast_connectable(&req, false);
1717
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001718 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1719 hci_conn_num(hdev, LE_LINK) == 0) {
1720 disable_advertising(&req);
1721 enable_advertising(&req);
1722 }
1723
Johan Hedberg2b76f452013-03-15 17:07:04 -05001724 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001725 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001726 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001727 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001728 err = set_connectable_update_settings(hdev, sk,
1729 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001730 goto failed;
1731 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732
1733failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001734 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001735 return err;
1736}
1737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001738static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001739 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001740{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001741 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001742 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001743 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001744
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001745 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001746
Johan Hedberga7e80f22013-01-09 16:05:19 +02001747 if (cp->val != 0x00 && cp->val != 0x01)
1748 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1749 MGMT_STATUS_INVALID_PARAMS);
1750
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001751 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001752
1753 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001754 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001755 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001756 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001757
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001758 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001759 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001760 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001761
Marcel Holtmann55594352013-10-06 16:11:57 -07001762 if (changed)
1763 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001764
Marcel Holtmann55594352013-10-06 16:11:57 -07001765unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001766 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001767 return err;
1768}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001769
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001770static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1771 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001772{
1773 struct mgmt_mode *cp = data;
1774 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001775 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001776 int err;
1777
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001778 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001779
Johan Hedberge6fe7982013-10-02 15:45:22 +03001780 status = mgmt_bredr_support(hdev);
1781 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001782 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001783 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001784
Johan Hedberga7e80f22013-01-09 16:05:19 +02001785 if (cp->val != 0x00 && cp->val != 0x01)
1786 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1787 MGMT_STATUS_INVALID_PARAMS);
1788
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001789 hci_dev_lock(hdev);
1790
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001791 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001792 bool changed = false;
1793
1794 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001795 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001796 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1797 changed = true;
1798 }
1799
1800 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1801 if (err < 0)
1802 goto failed;
1803
1804 if (changed)
1805 err = new_settings(hdev, sk);
1806
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001807 goto failed;
1808 }
1809
1810 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001811 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001812 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001813 goto failed;
1814 }
1815
1816 val = !!cp->val;
1817
1818 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1819 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1820 goto failed;
1821 }
1822
1823 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1824 if (!cmd) {
1825 err = -ENOMEM;
1826 goto failed;
1827 }
1828
1829 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1830 if (err < 0) {
1831 mgmt_pending_remove(cmd);
1832 goto failed;
1833 }
1834
1835failed:
1836 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001837 return err;
1838}
1839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001840static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001841{
1842 struct mgmt_mode *cp = data;
1843 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001844 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001845 int err;
1846
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001847 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001848
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001849 status = mgmt_bredr_support(hdev);
1850 if (status)
1851 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1852
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001853 if (!lmp_ssp_capable(hdev))
1854 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1855 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001856
Johan Hedberga7e80f22013-01-09 16:05:19 +02001857 if (cp->val != 0x00 && cp->val != 0x01)
1858 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1859 MGMT_STATUS_INVALID_PARAMS);
1860
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001861 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001862
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001863 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001864 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001865
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001866 if (cp->val) {
1867 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1868 &hdev->dev_flags);
1869 } else {
1870 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1871 &hdev->dev_flags);
1872 if (!changed)
1873 changed = test_and_clear_bit(HCI_HS_ENABLED,
1874 &hdev->dev_flags);
1875 else
1876 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001877 }
1878
1879 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1880 if (err < 0)
1881 goto failed;
1882
1883 if (changed)
1884 err = new_settings(hdev, sk);
1885
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001886 goto failed;
1887 }
1888
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001889 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1890 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001891 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1892 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001893 goto failed;
1894 }
1895
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001896 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001897 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1898 goto failed;
1899 }
1900
1901 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1902 if (!cmd) {
1903 err = -ENOMEM;
1904 goto failed;
1905 }
1906
Johan Hedberg37699722014-06-24 14:00:27 +03001907 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1908 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1909 sizeof(cp->val), &cp->val);
1910
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001911 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001912 if (err < 0) {
1913 mgmt_pending_remove(cmd);
1914 goto failed;
1915 }
1916
1917failed:
1918 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001919 return err;
1920}
1921
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001922static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001923{
1924 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001925 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001926 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001927 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001928
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001929 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001930
Johan Hedberge6fe7982013-10-02 15:45:22 +03001931 status = mgmt_bredr_support(hdev);
1932 if (status)
1933 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001934
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001935 if (!lmp_ssp_capable(hdev))
1936 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1937 MGMT_STATUS_NOT_SUPPORTED);
1938
1939 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1940 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1941 MGMT_STATUS_REJECTED);
1942
Johan Hedberga7e80f22013-01-09 16:05:19 +02001943 if (cp->val != 0x00 && cp->val != 0x01)
1944 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1945 MGMT_STATUS_INVALID_PARAMS);
1946
Marcel Holtmannee392692013-10-01 22:59:23 -07001947 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001948
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001949 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001950 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001951 } else {
1952 if (hdev_is_powered(hdev)) {
1953 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1954 MGMT_STATUS_REJECTED);
1955 goto unlock;
1956 }
1957
Marcel Holtmannee392692013-10-01 22:59:23 -07001958 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001959 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001960
1961 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1962 if (err < 0)
1963 goto unlock;
1964
1965 if (changed)
1966 err = new_settings(hdev, sk);
1967
1968unlock:
1969 hci_dev_unlock(hdev);
1970 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001971}
1972
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001973static void le_enable_complete(struct hci_dev *hdev, u8 status)
1974{
1975 struct cmd_lookup match = { NULL, hdev };
1976
1977 if (status) {
1978 u8 mgmt_err = mgmt_status(status);
1979
1980 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1981 &mgmt_err);
1982 return;
1983 }
1984
1985 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1986
1987 new_settings(hdev, match.sk);
1988
1989 if (match.sk)
1990 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001991
1992 /* Make sure the controller has a good default for
1993 * advertising data. Restrict the update to when LE
1994 * has actually been enabled. During power on, the
1995 * update in powered_update_hci will take care of it.
1996 */
1997 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1998 struct hci_request req;
1999
2000 hci_dev_lock(hdev);
2001
2002 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002003 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002004 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002005 hci_req_run(&req, NULL);
2006
2007 hci_dev_unlock(hdev);
2008 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002009}
2010
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002011static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012{
2013 struct mgmt_mode *cp = data;
2014 struct hci_cp_write_le_host_supported hci_cp;
2015 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002016 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002017 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002018 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002019
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002020 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002021
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002022 if (!lmp_le_capable(hdev))
2023 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2024 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002025
Johan Hedberga7e80f22013-01-09 16:05:19 +02002026 if (cp->val != 0x00 && cp->val != 0x01)
2027 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2028 MGMT_STATUS_INVALID_PARAMS);
2029
Johan Hedbergc73eee92013-04-19 18:35:21 +03002030 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002031 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002032 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2033 MGMT_STATUS_REJECTED);
2034
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002035 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002036
2037 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002038 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002039
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002040 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002041 bool changed = false;
2042
2043 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2044 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2045 changed = true;
2046 }
2047
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002048 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2049 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002050 changed = true;
2051 }
2052
Johan Hedberg06199cf2012-02-22 16:37:11 +02002053 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2054 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002055 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002056
2057 if (changed)
2058 err = new_settings(hdev, sk);
2059
Johan Hedberg1de028c2012-02-29 19:55:35 -08002060 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002061 }
2062
Johan Hedberg4375f102013-09-25 13:26:10 +03002063 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2064 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002066 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002067 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002068 }
2069
2070 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2071 if (!cmd) {
2072 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002073 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002074 }
2075
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002076 hci_req_init(&req, hdev);
2077
Johan Hedberg06199cf2012-02-22 16:37:11 +02002078 memset(&hci_cp, 0, sizeof(hci_cp));
2079
2080 if (val) {
2081 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002082 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002083 } else {
2084 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2085 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002086 }
2087
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002088 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2089 &hci_cp);
2090
2091 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302092 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002093 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002094
Johan Hedberg1de028c2012-02-29 19:55:35 -08002095unlock:
2096 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002097 return err;
2098}
2099
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002100/* This is a helper function to test for pending mgmt commands that can
2101 * cause CoD or EIR HCI commands. We can only allow one such pending
2102 * mgmt command at a time since otherwise we cannot easily track what
2103 * the current values are, will be, and based on that calculate if a new
2104 * HCI command needs to be sent and if yes with what value.
2105 */
2106static bool pending_eir_or_class(struct hci_dev *hdev)
2107{
2108 struct pending_cmd *cmd;
2109
2110 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2111 switch (cmd->opcode) {
2112 case MGMT_OP_ADD_UUID:
2113 case MGMT_OP_REMOVE_UUID:
2114 case MGMT_OP_SET_DEV_CLASS:
2115 case MGMT_OP_SET_POWERED:
2116 return true;
2117 }
2118 }
2119
2120 return false;
2121}
2122
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002123static const u8 bluetooth_base_uuid[] = {
2124 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2125 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2126};
2127
2128static u8 get_uuid_size(const u8 *uuid)
2129{
2130 u32 val;
2131
2132 if (memcmp(uuid, bluetooth_base_uuid, 12))
2133 return 128;
2134
2135 val = get_unaligned_le32(&uuid[12]);
2136 if (val > 0xffff)
2137 return 32;
2138
2139 return 16;
2140}
2141
Johan Hedberg92da6092013-03-15 17:06:55 -05002142static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2143{
2144 struct pending_cmd *cmd;
2145
2146 hci_dev_lock(hdev);
2147
2148 cmd = mgmt_pending_find(mgmt_op, hdev);
2149 if (!cmd)
2150 goto unlock;
2151
2152 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2153 hdev->dev_class, 3);
2154
2155 mgmt_pending_remove(cmd);
2156
2157unlock:
2158 hci_dev_unlock(hdev);
2159}
2160
2161static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2162{
2163 BT_DBG("status 0x%02x", status);
2164
2165 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2166}
2167
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002168static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002169{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002170 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002171 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002172 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002173 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002174 int err;
2175
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002176 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002177
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002178 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002179
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002180 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002181 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002182 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002183 goto failed;
2184 }
2185
Andre Guedes92c4c202012-06-07 19:05:44 -03002186 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002187 if (!uuid) {
2188 err = -ENOMEM;
2189 goto failed;
2190 }
2191
2192 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002193 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002194 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002195
Johan Hedbergde66aa62013-01-27 00:31:27 +02002196 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002197
Johan Hedberg890ea892013-03-15 17:06:52 -05002198 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002199
Johan Hedberg890ea892013-03-15 17:06:52 -05002200 update_class(&req);
2201 update_eir(&req);
2202
Johan Hedberg92da6092013-03-15 17:06:55 -05002203 err = hci_req_run(&req, add_uuid_complete);
2204 if (err < 0) {
2205 if (err != -ENODATA)
2206 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002208 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002209 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002210 goto failed;
2211 }
2212
2213 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002214 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002215 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002216 goto failed;
2217 }
2218
2219 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002220
2221failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002222 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002223 return err;
2224}
2225
Johan Hedberg24b78d02012-02-23 23:24:30 +02002226static bool enable_service_cache(struct hci_dev *hdev)
2227{
2228 if (!hdev_is_powered(hdev))
2229 return false;
2230
2231 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002232 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2233 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002234 return true;
2235 }
2236
2237 return false;
2238}
2239
Johan Hedberg92da6092013-03-15 17:06:55 -05002240static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2241{
2242 BT_DBG("status 0x%02x", status);
2243
2244 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2245}
2246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002248 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002249{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002250 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002251 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002252 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253 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 -05002254 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002255 int err, found;
2256
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002257 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002258
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002259 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002260
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002261 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002262 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002263 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002264 goto unlock;
2265 }
2266
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002267 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002268 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002269
Johan Hedberg24b78d02012-02-23 23:24:30 +02002270 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002271 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002272 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002273 goto unlock;
2274 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002275
Johan Hedberg9246a862012-02-23 21:33:16 +02002276 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002277 }
2278
2279 found = 0;
2280
Johan Hedberg056341c2013-01-27 00:31:30 +02002281 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002282 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2283 continue;
2284
2285 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002286 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002287 found++;
2288 }
2289
2290 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002291 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002292 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002293 goto unlock;
2294 }
2295
Johan Hedberg9246a862012-02-23 21:33:16 +02002296update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002297 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002298
Johan Hedberg890ea892013-03-15 17:06:52 -05002299 update_class(&req);
2300 update_eir(&req);
2301
Johan Hedberg92da6092013-03-15 17:06:55 -05002302 err = hci_req_run(&req, remove_uuid_complete);
2303 if (err < 0) {
2304 if (err != -ENODATA)
2305 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002307 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002308 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002309 goto unlock;
2310 }
2311
2312 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002313 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002314 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002315 goto unlock;
2316 }
2317
2318 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002319
2320unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002321 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322 return err;
2323}
2324
Johan Hedberg92da6092013-03-15 17:06:55 -05002325static void set_class_complete(struct hci_dev *hdev, u8 status)
2326{
2327 BT_DBG("status 0x%02x", status);
2328
2329 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2330}
2331
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002332static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002333 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002334{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002335 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002336 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002337 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002338 int err;
2339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002340 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002341
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002342 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002343 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2344 MGMT_STATUS_NOT_SUPPORTED);
2345
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002346 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002347
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002348 if (pending_eir_or_class(hdev)) {
2349 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2350 MGMT_STATUS_BUSY);
2351 goto unlock;
2352 }
2353
2354 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2355 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2356 MGMT_STATUS_INVALID_PARAMS);
2357 goto unlock;
2358 }
2359
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002360 hdev->major_class = cp->major;
2361 hdev->minor_class = cp->minor;
2362
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002363 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002364 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002365 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002366 goto unlock;
2367 }
2368
Johan Hedberg890ea892013-03-15 17:06:52 -05002369 hci_req_init(&req, hdev);
2370
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002371 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002372 hci_dev_unlock(hdev);
2373 cancel_delayed_work_sync(&hdev->service_cache);
2374 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002375 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002376 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002377
Johan Hedberg890ea892013-03-15 17:06:52 -05002378 update_class(&req);
2379
Johan Hedberg92da6092013-03-15 17:06:55 -05002380 err = hci_req_run(&req, set_class_complete);
2381 if (err < 0) {
2382 if (err != -ENODATA)
2383 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002384
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002385 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002386 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002387 goto unlock;
2388 }
2389
2390 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002391 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002392 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002393 goto unlock;
2394 }
2395
2396 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002397
Johan Hedbergb5235a62012-02-21 14:32:24 +02002398unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002399 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002400 return err;
2401}
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002404 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002405{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002406 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002407 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002408 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002409 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002410
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002411 BT_DBG("request for %s", hdev->name);
2412
2413 if (!lmp_bredr_capable(hdev))
2414 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2415 MGMT_STATUS_NOT_SUPPORTED);
2416
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002417 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002418
Johan Hedberg86742e12011-11-07 23:13:38 +02002419 expected_len = sizeof(*cp) + key_count *
2420 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002421 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002422 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002423 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002424 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002425 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002426 }
2427
Johan Hedberg4ae14302013-01-20 14:27:13 +02002428 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2429 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2430 MGMT_STATUS_INVALID_PARAMS);
2431
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002432 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002433 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002434
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002435 for (i = 0; i < key_count; i++) {
2436 struct mgmt_link_key_info *key = &cp->keys[i];
2437
Marcel Holtmann8e991132014-01-10 02:07:25 -08002438 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002439 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2440 MGMT_STATUS_INVALID_PARAMS);
2441 }
2442
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002443 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002444
2445 hci_link_keys_clear(hdev);
2446
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002447 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002448 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2449 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002450 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002451 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2452 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002453
2454 if (changed)
2455 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002456
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002457 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002458 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002459
Johan Hedberg58e92932014-06-24 14:00:26 +03002460 /* Always ignore debug keys and require a new pairing if
2461 * the user wants to use them.
2462 */
2463 if (key->type == HCI_LK_DEBUG_COMBINATION)
2464 continue;
2465
Johan Hedberg7652ff62014-06-24 13:15:49 +03002466 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2467 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002468 }
2469
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002470 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002471
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002472 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002473
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002474 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002475}
2476
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002477static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002478 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002479{
2480 struct mgmt_ev_device_unpaired ev;
2481
2482 bacpy(&ev.addr.bdaddr, bdaddr);
2483 ev.addr.type = addr_type;
2484
2485 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002486 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002487}
2488
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002491{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002492 struct mgmt_cp_unpair_device *cp = data;
2493 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002494 struct hci_cp_disconnect dc;
2495 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002496 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002497 int err;
2498
Johan Hedberga8a1d192011-11-10 15:54:38 +02002499 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002500 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2501 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002502
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002503 if (!bdaddr_type_is_valid(cp->addr.type))
2504 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2505 MGMT_STATUS_INVALID_PARAMS,
2506 &rp, sizeof(rp));
2507
Johan Hedberg118da702013-01-20 14:27:20 +02002508 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2509 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2510 MGMT_STATUS_INVALID_PARAMS,
2511 &rp, sizeof(rp));
2512
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002513 hci_dev_lock(hdev);
2514
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002515 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002516 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002517 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002518 goto unlock;
2519 }
2520
Johan Hedberge0b2b272014-02-18 17:14:31 +02002521 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002522 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002523 } else {
2524 u8 addr_type;
2525
2526 if (cp->addr.type == BDADDR_LE_PUBLIC)
2527 addr_type = ADDR_LE_DEV_PUBLIC;
2528 else
2529 addr_type = ADDR_LE_DEV_RANDOM;
2530
Johan Hedberga7ec7332014-02-18 17:14:35 +02002531 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2532
Andre Guedesa9b0a042014-02-26 20:21:52 -03002533 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2534
Johan Hedberge0b2b272014-02-18 17:14:31 +02002535 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2536 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002537
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002538 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002539 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002540 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002541 goto unlock;
2542 }
2543
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002544 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002545 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002546 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002547 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002548 else
2549 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002550 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002551 } else {
2552 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002553 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002554
Johan Hedberga8a1d192011-11-10 15:54:38 +02002555 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002556 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002557 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002558 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002559 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002560 }
2561
Johan Hedberg124f6e32012-02-09 13:50:12 +02002562 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002563 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002564 if (!cmd) {
2565 err = -ENOMEM;
2566 goto unlock;
2567 }
2568
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002569 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002570 dc.reason = 0x13; /* Remote User Terminated Connection */
2571 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2572 if (err < 0)
2573 mgmt_pending_remove(cmd);
2574
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002575unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002576 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002577 return err;
2578}
2579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002580static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002581 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002583 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002584 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002585 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002586 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002587 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002588 int err;
2589
2590 BT_DBG("");
2591
Johan Hedberg06a63b12013-01-20 14:27:21 +02002592 memset(&rp, 0, sizeof(rp));
2593 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2594 rp.addr.type = cp->addr.type;
2595
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002596 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002597 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2598 MGMT_STATUS_INVALID_PARAMS,
2599 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002600
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002601 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002602
2603 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002604 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2605 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002606 goto failed;
2607 }
2608
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002609 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002610 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2611 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002612 goto failed;
2613 }
2614
Andre Guedes591f47f2012-04-24 21:02:49 -03002615 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002616 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2617 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002618 else
2619 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002620
Vishal Agarwalf9607272012-06-13 05:32:43 +05302621 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002622 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2623 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002624 goto failed;
2625 }
2626
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002627 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002628 if (!cmd) {
2629 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002630 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002631 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002632
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002633 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002634 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002635
2636 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2637 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002638 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002639
2640failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002641 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002642 return err;
2643}
2644
Andre Guedes57c14772012-04-24 21:02:50 -03002645static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002646{
2647 switch (link_type) {
2648 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002649 switch (addr_type) {
2650 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002651 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002652
Johan Hedberg48264f02011-11-09 13:58:58 +02002653 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002654 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002655 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002656 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002657
Johan Hedberg4c659c32011-11-07 23:13:39 +02002658 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002659 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002660 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002661 }
2662}
2663
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002664static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2665 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002666{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002667 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002668 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002669 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002670 int err;
2671 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002672
2673 BT_DBG("");
2674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002675 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002676
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002677 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002678 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002679 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002680 goto unlock;
2681 }
2682
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002683 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002684 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2685 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002686 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002687 }
2688
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002689 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002690 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002691 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002692 err = -ENOMEM;
2693 goto unlock;
2694 }
2695
Johan Hedberg2784eb42011-01-21 13:56:35 +02002696 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002697 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002698 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2699 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002700 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002701 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002702 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002703 continue;
2704 i++;
2705 }
2706
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002707 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002708
Johan Hedberg4c659c32011-11-07 23:13:39 +02002709 /* Recalculate length in case of filtered SCO connections, etc */
2710 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002711
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002712 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002714
Johan Hedberga38528f2011-01-22 06:46:43 +02002715 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002716
2717unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002718 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002719 return err;
2720}
2721
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002722static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002723 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002724{
2725 struct pending_cmd *cmd;
2726 int err;
2727
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002728 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002729 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002730 if (!cmd)
2731 return -ENOMEM;
2732
Johan Hedbergd8457692012-02-17 14:24:57 +02002733 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002734 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002735 if (err < 0)
2736 mgmt_pending_remove(cmd);
2737
2738 return err;
2739}
2740
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002741static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002742 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002743{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002744 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002745 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002746 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002747 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002748 int err;
2749
2750 BT_DBG("");
2751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002752 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002753
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002754 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002757 goto failed;
2758 }
2759
Johan Hedbergd8457692012-02-17 14:24:57 +02002760 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002761 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002762 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002763 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002764 goto failed;
2765 }
2766
2767 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002768 struct mgmt_cp_pin_code_neg_reply ncp;
2769
2770 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002771
2772 BT_ERR("PIN code is not 16 bytes long");
2773
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002774 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002775 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002776 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002777 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002778
2779 goto failed;
2780 }
2781
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002782 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002783 if (!cmd) {
2784 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002785 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002786 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002787
Johan Hedbergd8457692012-02-17 14:24:57 +02002788 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002789 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002790 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002791
2792 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2793 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002794 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002795
2796failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002797 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002798 return err;
2799}
2800
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002801static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2802 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002803{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002804 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002805
2806 BT_DBG("");
2807
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002808 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2809 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2810 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2811
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002812 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002813
2814 hdev->io_capability = cp->io_capability;
2815
2816 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002817 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002818
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002819 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002820
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002821 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2822 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002823}
2824
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002825static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002826{
2827 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002828 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002829
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002830 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002831 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2832 continue;
2833
Johan Hedberge9a416b2011-02-19 12:05:56 -03002834 if (cmd->user_data != conn)
2835 continue;
2836
2837 return cmd;
2838 }
2839
2840 return NULL;
2841}
2842
2843static void pairing_complete(struct pending_cmd *cmd, u8 status)
2844{
2845 struct mgmt_rp_pair_device rp;
2846 struct hci_conn *conn = cmd->user_data;
2847
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002848 bacpy(&rp.addr.bdaddr, &conn->dst);
2849 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002850
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002851 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002852 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002853
2854 /* So we don't get further callbacks for this connection */
2855 conn->connect_cfm_cb = NULL;
2856 conn->security_cfm_cb = NULL;
2857 conn->disconn_cfm_cb = NULL;
2858
David Herrmann76a68ba2013-04-06 20:28:37 +02002859 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002860
Johan Hedberga664b5b2011-02-19 12:06:02 -03002861 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002862}
2863
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002864void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2865{
2866 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2867 struct pending_cmd *cmd;
2868
2869 cmd = find_pairing(conn);
2870 if (cmd)
2871 pairing_complete(cmd, status);
2872}
2873
Johan Hedberge9a416b2011-02-19 12:05:56 -03002874static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2875{
2876 struct pending_cmd *cmd;
2877
2878 BT_DBG("status %u", status);
2879
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002880 cmd = find_pairing(conn);
2881 if (!cmd)
2882 BT_DBG("Unable to find a pending command");
2883 else
Johan Hedberge2113262012-02-18 15:20:03 +02002884 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002885}
2886
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002887static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302888{
2889 struct pending_cmd *cmd;
2890
2891 BT_DBG("status %u", status);
2892
2893 if (!status)
2894 return;
2895
2896 cmd = find_pairing(conn);
2897 if (!cmd)
2898 BT_DBG("Unable to find a pending command");
2899 else
2900 pairing_complete(cmd, mgmt_status(status));
2901}
2902
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002903static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002904 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002905{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002906 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002907 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002908 struct pending_cmd *cmd;
2909 u8 sec_level, auth_type;
2910 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002911 int err;
2912
2913 BT_DBG("");
2914
Szymon Jancf950a30e2013-01-18 12:48:07 +01002915 memset(&rp, 0, sizeof(rp));
2916 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2917 rp.addr.type = cp->addr.type;
2918
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002919 if (!bdaddr_type_is_valid(cp->addr.type))
2920 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2921 MGMT_STATUS_INVALID_PARAMS,
2922 &rp, sizeof(rp));
2923
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002924 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2925 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2926 MGMT_STATUS_INVALID_PARAMS,
2927 &rp, sizeof(rp));
2928
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002929 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002930
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002931 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002932 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2933 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002934 goto unlock;
2935 }
2936
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002937 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002938 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002939
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002940 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002941 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2942 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002943 } else {
2944 u8 addr_type;
2945
2946 /* Convert from L2CAP channel address type to HCI address type
2947 */
2948 if (cp->addr.type == BDADDR_LE_PUBLIC)
2949 addr_type = ADDR_LE_DEV_PUBLIC;
2950 else
2951 addr_type = ADDR_LE_DEV_RANDOM;
2952
Marcel Holtmann7c264b12014-06-30 12:34:40 +02002953 /* When pairing a new device, it is expected to remember
2954 * this device for future connections. Adding the connection
2955 * parameter information ahead of time allows tracking
2956 * of the slave preferred values and will speed up any
2957 * further connection establishment.
2958 *
2959 * If connection parameters already exist, then they
2960 * will be kept and this function does nothing.
2961 */
2962 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
2963
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002964 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002965 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002966 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002967
Ville Tervo30e76272011-02-22 16:10:53 -03002968 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002969 int status;
2970
2971 if (PTR_ERR(conn) == -EBUSY)
2972 status = MGMT_STATUS_BUSY;
2973 else
2974 status = MGMT_STATUS_CONNECT_FAILED;
2975
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002976 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002977 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002979 goto unlock;
2980 }
2981
2982 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002983 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002984 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002986 goto unlock;
2987 }
2988
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002989 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002990 if (!cmd) {
2991 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002992 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002993 goto unlock;
2994 }
2995
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002996 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002997 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002998 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002999 conn->security_cfm_cb = pairing_complete_cb;
3000 conn->disconn_cfm_cb = pairing_complete_cb;
3001 } else {
3002 conn->connect_cfm_cb = le_pairing_complete_cb;
3003 conn->security_cfm_cb = le_pairing_complete_cb;
3004 conn->disconn_cfm_cb = le_pairing_complete_cb;
3005 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003006
Johan Hedberge9a416b2011-02-19 12:05:56 -03003007 conn->io_capability = cp->io_cap;
3008 cmd->user_data = conn;
3009
3010 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003011 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003012 pairing_complete(cmd, 0);
3013
3014 err = 0;
3015
3016unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003017 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003018 return err;
3019}
3020
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003021static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3022 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003023{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003024 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003025 struct pending_cmd *cmd;
3026 struct hci_conn *conn;
3027 int err;
3028
3029 BT_DBG("");
3030
Johan Hedberg28424702012-02-02 04:02:29 +02003031 hci_dev_lock(hdev);
3032
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003033 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003034 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003035 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003036 goto unlock;
3037 }
3038
Johan Hedberg28424702012-02-02 04:02:29 +02003039 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3040 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003041 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003042 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003043 goto unlock;
3044 }
3045
3046 conn = cmd->user_data;
3047
3048 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003049 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003050 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003051 goto unlock;
3052 }
3053
3054 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3055
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003056 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003057 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003058unlock:
3059 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003060 return err;
3061}
3062
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003063static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003064 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003065 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003066{
Johan Hedberga5c29682011-02-19 12:05:57 -03003067 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003068 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003069 int err;
3070
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003071 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003072
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003073 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003074 err = cmd_complete(sk, hdev->id, mgmt_op,
3075 MGMT_STATUS_NOT_POWERED, addr,
3076 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003077 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003078 }
3079
Johan Hedberg1707c602013-03-15 17:07:15 -05003080 if (addr->type == BDADDR_BREDR)
3081 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003082 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003083 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003084
Johan Hedberg272d90d2012-02-09 15:26:12 +02003085 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003086 err = cmd_complete(sk, hdev->id, mgmt_op,
3087 MGMT_STATUS_NOT_CONNECTED, addr,
3088 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003089 goto done;
3090 }
3091
Johan Hedberg1707c602013-03-15 17:07:15 -05003092 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003093 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003094 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003095 err = cmd_complete(sk, hdev->id, mgmt_op,
3096 MGMT_STATUS_SUCCESS, addr,
3097 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003098 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003099 err = cmd_complete(sk, hdev->id, mgmt_op,
3100 MGMT_STATUS_FAILED, addr,
3101 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003102
Brian Gix47c15e22011-11-16 13:53:14 -08003103 goto done;
3104 }
3105
Johan Hedberg1707c602013-03-15 17:07:15 -05003106 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003107 if (!cmd) {
3108 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003109 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003110 }
3111
Brian Gix0df4c182011-11-16 13:53:13 -08003112 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003113 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3114 struct hci_cp_user_passkey_reply cp;
3115
Johan Hedberg1707c602013-03-15 17:07:15 -05003116 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003117 cp.passkey = passkey;
3118 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3119 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003120 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3121 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003122
Johan Hedberga664b5b2011-02-19 12:06:02 -03003123 if (err < 0)
3124 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003125
Brian Gix0df4c182011-11-16 13:53:13 -08003126done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003127 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003128 return err;
3129}
3130
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303131static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3132 void *data, u16 len)
3133{
3134 struct mgmt_cp_pin_code_neg_reply *cp = data;
3135
3136 BT_DBG("");
3137
Johan Hedberg1707c602013-03-15 17:07:15 -05003138 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303139 MGMT_OP_PIN_CODE_NEG_REPLY,
3140 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3141}
3142
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003143static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3144 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003145{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003146 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003147
3148 BT_DBG("");
3149
3150 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003151 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003152 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003153
Johan Hedberg1707c602013-03-15 17:07:15 -05003154 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003155 MGMT_OP_USER_CONFIRM_REPLY,
3156 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003157}
3158
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003159static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003160 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003161{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003162 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003163
3164 BT_DBG("");
3165
Johan Hedberg1707c602013-03-15 17:07:15 -05003166 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3168 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003169}
3170
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003171static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3172 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003173{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003174 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003175
3176 BT_DBG("");
3177
Johan Hedberg1707c602013-03-15 17:07:15 -05003178 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179 MGMT_OP_USER_PASSKEY_REPLY,
3180 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003181}
3182
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003183static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003184 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003185{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003186 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003187
3188 BT_DBG("");
3189
Johan Hedberg1707c602013-03-15 17:07:15 -05003190 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003191 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3192 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003193}
3194
Johan Hedberg13928972013-03-15 17:07:00 -05003195static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003196{
Johan Hedberg13928972013-03-15 17:07:00 -05003197 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003198 struct hci_cp_write_local_name cp;
3199
Johan Hedberg13928972013-03-15 17:07:00 -05003200 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003201
Johan Hedberg890ea892013-03-15 17:06:52 -05003202 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003203}
3204
Johan Hedberg13928972013-03-15 17:07:00 -05003205static void set_name_complete(struct hci_dev *hdev, u8 status)
3206{
3207 struct mgmt_cp_set_local_name *cp;
3208 struct pending_cmd *cmd;
3209
3210 BT_DBG("status 0x%02x", status);
3211
3212 hci_dev_lock(hdev);
3213
3214 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3215 if (!cmd)
3216 goto unlock;
3217
3218 cp = cmd->param;
3219
3220 if (status)
3221 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3222 mgmt_status(status));
3223 else
3224 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3225 cp, sizeof(*cp));
3226
3227 mgmt_pending_remove(cmd);
3228
3229unlock:
3230 hci_dev_unlock(hdev);
3231}
3232
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003233static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003234 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003235{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003236 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003237 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003238 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003239 int err;
3240
3241 BT_DBG("");
3242
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003243 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003244
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003245 /* If the old values are the same as the new ones just return a
3246 * direct command complete event.
3247 */
3248 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3249 !memcmp(hdev->short_name, cp->short_name,
3250 sizeof(hdev->short_name))) {
3251 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3252 data, len);
3253 goto failed;
3254 }
3255
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003256 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003257
Johan Hedbergb5235a62012-02-21 14:32:24 +02003258 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003259 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003260
3261 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003262 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003263 if (err < 0)
3264 goto failed;
3265
3266 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003268
Johan Hedbergb5235a62012-02-21 14:32:24 +02003269 goto failed;
3270 }
3271
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003272 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003273 if (!cmd) {
3274 err = -ENOMEM;
3275 goto failed;
3276 }
3277
Johan Hedberg13928972013-03-15 17:07:00 -05003278 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3279
Johan Hedberg890ea892013-03-15 17:06:52 -05003280 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003281
3282 if (lmp_bredr_capable(hdev)) {
3283 update_name(&req);
3284 update_eir(&req);
3285 }
3286
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003287 /* The name is stored in the scan response data and so
3288 * no need to udpate the advertising data here.
3289 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003290 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003291 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003292
Johan Hedberg13928972013-03-15 17:07:00 -05003293 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003294 if (err < 0)
3295 mgmt_pending_remove(cmd);
3296
3297failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003298 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003299 return err;
3300}
3301
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003302static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003303 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003304{
Szymon Jancc35938b2011-03-22 13:12:21 +01003305 struct pending_cmd *cmd;
3306 int err;
3307
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003308 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003309
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003310 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003311
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003312 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003315 goto unlock;
3316 }
3317
Andre Guedes9a1a1992012-07-24 15:03:48 -03003318 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003319 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003320 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003321 goto unlock;
3322 }
3323
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003324 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003325 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003326 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003327 goto unlock;
3328 }
3329
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003330 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003331 if (!cmd) {
3332 err = -ENOMEM;
3333 goto unlock;
3334 }
3335
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003336 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3337 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3338 0, NULL);
3339 else
3340 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3341
Szymon Jancc35938b2011-03-22 13:12:21 +01003342 if (err < 0)
3343 mgmt_pending_remove(cmd);
3344
3345unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003346 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003347 return err;
3348}
3349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003350static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003351 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003352{
Szymon Janc2763eda2011-03-22 13:12:22 +01003353 int err;
3354
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003355 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003356
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003357 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003358
Marcel Holtmannec109112014-01-10 02:07:30 -08003359 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3360 struct mgmt_cp_add_remote_oob_data *cp = data;
3361 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003362
Marcel Holtmannec109112014-01-10 02:07:30 -08003363 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3364 cp->hash, cp->randomizer);
3365 if (err < 0)
3366 status = MGMT_STATUS_FAILED;
3367 else
3368 status = MGMT_STATUS_SUCCESS;
3369
3370 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3371 status, &cp->addr, sizeof(cp->addr));
3372 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3373 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3374 u8 status;
3375
3376 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3377 cp->hash192,
3378 cp->randomizer192,
3379 cp->hash256,
3380 cp->randomizer256);
3381 if (err < 0)
3382 status = MGMT_STATUS_FAILED;
3383 else
3384 status = MGMT_STATUS_SUCCESS;
3385
3386 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3387 status, &cp->addr, sizeof(cp->addr));
3388 } else {
3389 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3390 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3391 MGMT_STATUS_INVALID_PARAMS);
3392 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003393
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003394 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003395 return err;
3396}
3397
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003398static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003399 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003400{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003401 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003402 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003403 int err;
3404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003405 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003406
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003407 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003408
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003409 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003410 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003411 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003412 else
Szymon Janca6785be2012-12-13 15:11:21 +01003413 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003414
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003415 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003416 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003417
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003418 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003419 return err;
3420}
3421
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003422static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3423{
3424 struct pending_cmd *cmd;
3425 u8 type;
3426 int err;
3427
3428 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3429
3430 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3431 if (!cmd)
3432 return -ENOENT;
3433
3434 type = hdev->discovery.type;
3435
3436 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3437 &type, sizeof(type));
3438 mgmt_pending_remove(cmd);
3439
3440 return err;
3441}
3442
Andre Guedes7c307722013-04-30 15:29:28 -03003443static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3444{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003445 unsigned long timeout = 0;
3446
Andre Guedes7c307722013-04-30 15:29:28 -03003447 BT_DBG("status %d", status);
3448
3449 if (status) {
3450 hci_dev_lock(hdev);
3451 mgmt_start_discovery_failed(hdev, status);
3452 hci_dev_unlock(hdev);
3453 return;
3454 }
3455
3456 hci_dev_lock(hdev);
3457 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3458 hci_dev_unlock(hdev);
3459
3460 switch (hdev->discovery.type) {
3461 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003462 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003463 break;
3464
3465 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003466 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003467 break;
3468
3469 case DISCOV_TYPE_BREDR:
3470 break;
3471
3472 default:
3473 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3474 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003475
3476 if (!timeout)
3477 return;
3478
3479 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003480}
3481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003482static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003483 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003484{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003485 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003486 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003487 struct hci_cp_le_set_scan_param param_cp;
3488 struct hci_cp_le_set_scan_enable enable_cp;
3489 struct hci_cp_inquiry inq_cp;
3490 struct hci_request req;
3491 /* General inquiry access code (GIAC) */
3492 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003493 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003494 int err;
3495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003496 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003497
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003498 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003499
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003500 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003501 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003503 goto failed;
3504 }
3505
Andre Guedes642be6c2012-03-21 00:03:37 -03003506 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3507 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3508 MGMT_STATUS_BUSY);
3509 goto failed;
3510 }
3511
Johan Hedbergff9ef572012-01-04 14:23:45 +02003512 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003513 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003514 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003515 goto failed;
3516 }
3517
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003518 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003519 if (!cmd) {
3520 err = -ENOMEM;
3521 goto failed;
3522 }
3523
Andre Guedes4aab14e2012-02-17 20:39:36 -03003524 hdev->discovery.type = cp->type;
3525
Andre Guedes7c307722013-04-30 15:29:28 -03003526 hci_req_init(&req, hdev);
3527
Andre Guedes4aab14e2012-02-17 20:39:36 -03003528 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003529 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003530 status = mgmt_bredr_support(hdev);
3531 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003532 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003533 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003534 mgmt_pending_remove(cmd);
3535 goto failed;
3536 }
3537
Andre Guedes7c307722013-04-30 15:29:28 -03003538 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3539 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3540 MGMT_STATUS_BUSY);
3541 mgmt_pending_remove(cmd);
3542 goto failed;
3543 }
3544
3545 hci_inquiry_cache_flush(hdev);
3546
3547 memset(&inq_cp, 0, sizeof(inq_cp));
3548 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003549 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003550 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003551 break;
3552
3553 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003554 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003555 status = mgmt_le_support(hdev);
3556 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003557 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003558 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003559 mgmt_pending_remove(cmd);
3560 goto failed;
3561 }
3562
Andre Guedes7c307722013-04-30 15:29:28 -03003563 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003564 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003565 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3566 MGMT_STATUS_NOT_SUPPORTED);
3567 mgmt_pending_remove(cmd);
3568 goto failed;
3569 }
3570
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003571 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003572 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3573 MGMT_STATUS_REJECTED);
3574 mgmt_pending_remove(cmd);
3575 goto failed;
3576 }
3577
Andre Guedesc54c3862014-02-26 20:21:50 -03003578 /* If controller is scanning, it means the background scanning
3579 * is running. Thus, we should temporarily stop it in order to
3580 * set the discovery scanning parameters.
3581 */
3582 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3583 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003584
3585 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003586
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003587 /* All active scans will be done with either a resolvable
3588 * private address (when privacy feature has been enabled)
3589 * or unresolvable private address.
3590 */
3591 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003592 if (err < 0) {
3593 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3594 MGMT_STATUS_FAILED);
3595 mgmt_pending_remove(cmd);
3596 goto failed;
3597 }
3598
Andre Guedes7c307722013-04-30 15:29:28 -03003599 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003600 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3601 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003602 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003603 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3604 &param_cp);
3605
3606 memset(&enable_cp, 0, sizeof(enable_cp));
3607 enable_cp.enable = LE_SCAN_ENABLE;
3608 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3609 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3610 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003611 break;
3612
Andre Guedesf39799f2012-02-17 20:39:35 -03003613 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003614 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3615 MGMT_STATUS_INVALID_PARAMS);
3616 mgmt_pending_remove(cmd);
3617 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003618 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003619
Andre Guedes7c307722013-04-30 15:29:28 -03003620 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003621 if (err < 0)
3622 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003623 else
3624 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003625
3626failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003627 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003628 return err;
3629}
3630
Andre Guedes1183fdc2013-04-30 15:29:35 -03003631static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3632{
3633 struct pending_cmd *cmd;
3634 int err;
3635
3636 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3637 if (!cmd)
3638 return -ENOENT;
3639
3640 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3641 &hdev->discovery.type, sizeof(hdev->discovery.type));
3642 mgmt_pending_remove(cmd);
3643
3644 return err;
3645}
3646
Andre Guedes0e05bba2013-04-30 15:29:33 -03003647static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3648{
3649 BT_DBG("status %d", status);
3650
3651 hci_dev_lock(hdev);
3652
3653 if (status) {
3654 mgmt_stop_discovery_failed(hdev, status);
3655 goto unlock;
3656 }
3657
3658 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3659
3660unlock:
3661 hci_dev_unlock(hdev);
3662}
3663
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003664static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003665 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003666{
Johan Hedbergd9306502012-02-20 23:25:18 +02003667 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003668 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003669 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003670 int err;
3671
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003672 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003673
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003674 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003675
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003676 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003677 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003678 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3679 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003680 goto unlock;
3681 }
3682
3683 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003684 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003685 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3686 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003687 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003688 }
3689
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003690 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003691 if (!cmd) {
3692 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003693 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003694 }
3695
Andre Guedes0e05bba2013-04-30 15:29:33 -03003696 hci_req_init(&req, hdev);
3697
Johan Hedberg21a60d32014-06-10 14:05:58 +03003698 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003699
Johan Hedberg21a60d32014-06-10 14:05:58 +03003700 err = hci_req_run(&req, stop_discovery_complete);
3701 if (!err) {
3702 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003703 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003704 }
3705
Johan Hedberg21a60d32014-06-10 14:05:58 +03003706 mgmt_pending_remove(cmd);
3707
3708 /* If no HCI commands were sent we're done */
3709 if (err == -ENODATA) {
3710 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3711 &mgmt_cp->type, sizeof(mgmt_cp->type));
3712 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3713 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003714
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003715unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003716 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003717 return err;
3718}
3719
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003720static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003721 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003722{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003723 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003724 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725 int err;
3726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003727 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003728
Johan Hedberg561aafb2012-01-04 13:31:59 +02003729 hci_dev_lock(hdev);
3730
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003731 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003732 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3733 MGMT_STATUS_FAILED, &cp->addr,
3734 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003735 goto failed;
3736 }
3737
Johan Hedberga198e7b2012-02-17 14:27:06 +02003738 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003739 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003740 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3741 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3742 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003743 goto failed;
3744 }
3745
3746 if (cp->name_known) {
3747 e->name_state = NAME_KNOWN;
3748 list_del(&e->list);
3749 } else {
3750 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003751 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003752 }
3753
Johan Hedberge3846622013-01-09 15:29:33 +02003754 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3755 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003756
3757failed:
3758 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003759 return err;
3760}
3761
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003762static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003763 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003764{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003765 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003766 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003767 int err;
3768
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003769 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003770
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003771 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003772 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3773 MGMT_STATUS_INVALID_PARAMS,
3774 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003775
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003776 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003777
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003778 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003779 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003780 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003781 goto done;
3782 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003783
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003784 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3785 sk);
3786 status = MGMT_STATUS_SUCCESS;
3787
3788done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003789 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003790 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003791
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003792 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003793
3794 return err;
3795}
3796
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003797static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003798 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003799{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003800 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003801 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003802 int err;
3803
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003804 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003805
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003806 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003807 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3808 MGMT_STATUS_INVALID_PARAMS,
3809 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003810
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003811 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003812
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003813 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003814 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003815 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003816 goto done;
3817 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003818
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003819 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3820 sk);
3821 status = MGMT_STATUS_SUCCESS;
3822
3823done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003824 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003825 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003826
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003827 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003828
3829 return err;
3830}
3831
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003832static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3833 u16 len)
3834{
3835 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003836 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003837 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003838 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003839
3840 BT_DBG("%s", hdev->name);
3841
Szymon Jancc72d4b82012-03-16 16:02:57 +01003842 source = __le16_to_cpu(cp->source);
3843
3844 if (source > 0x0002)
3845 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3846 MGMT_STATUS_INVALID_PARAMS);
3847
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003848 hci_dev_lock(hdev);
3849
Szymon Jancc72d4b82012-03-16 16:02:57 +01003850 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003851 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3852 hdev->devid_product = __le16_to_cpu(cp->product);
3853 hdev->devid_version = __le16_to_cpu(cp->version);
3854
3855 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3856
Johan Hedberg890ea892013-03-15 17:06:52 -05003857 hci_req_init(&req, hdev);
3858 update_eir(&req);
3859 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003860
3861 hci_dev_unlock(hdev);
3862
3863 return err;
3864}
3865
Johan Hedberg4375f102013-09-25 13:26:10 +03003866static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3867{
3868 struct cmd_lookup match = { NULL, hdev };
3869
3870 if (status) {
3871 u8 mgmt_err = mgmt_status(status);
3872
3873 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3874 cmd_status_rsp, &mgmt_err);
3875 return;
3876 }
3877
3878 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3879 &match);
3880
3881 new_settings(hdev, match.sk);
3882
3883 if (match.sk)
3884 sock_put(match.sk);
3885}
3886
Marcel Holtmann21b51872013-10-10 09:47:53 -07003887static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3888 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003889{
3890 struct mgmt_mode *cp = data;
3891 struct pending_cmd *cmd;
3892 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003893 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003894 int err;
3895
3896 BT_DBG("request for %s", hdev->name);
3897
Johan Hedberge6fe7982013-10-02 15:45:22 +03003898 status = mgmt_le_support(hdev);
3899 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003900 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003901 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003902
3903 if (cp->val != 0x00 && cp->val != 0x01)
3904 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3905 MGMT_STATUS_INVALID_PARAMS);
3906
3907 hci_dev_lock(hdev);
3908
3909 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003910 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003911
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003912 /* The following conditions are ones which mean that we should
3913 * not do any HCI communication but directly send a mgmt
3914 * response to user space (after toggling the flag if
3915 * necessary).
3916 */
3917 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003918 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003919 bool changed = false;
3920
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003921 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3922 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003923 changed = true;
3924 }
3925
3926 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3927 if (err < 0)
3928 goto unlock;
3929
3930 if (changed)
3931 err = new_settings(hdev, sk);
3932
3933 goto unlock;
3934 }
3935
3936 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3937 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3938 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3939 MGMT_STATUS_BUSY);
3940 goto unlock;
3941 }
3942
3943 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3944 if (!cmd) {
3945 err = -ENOMEM;
3946 goto unlock;
3947 }
3948
3949 hci_req_init(&req, hdev);
3950
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003951 if (val)
3952 enable_advertising(&req);
3953 else
3954 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003955
3956 err = hci_req_run(&req, set_advertising_complete);
3957 if (err < 0)
3958 mgmt_pending_remove(cmd);
3959
3960unlock:
3961 hci_dev_unlock(hdev);
3962 return err;
3963}
3964
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003965static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3966 void *data, u16 len)
3967{
3968 struct mgmt_cp_set_static_address *cp = data;
3969 int err;
3970
3971 BT_DBG("%s", hdev->name);
3972
Marcel Holtmann62af4442013-10-02 22:10:32 -07003973 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003974 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003975 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003976
3977 if (hdev_is_powered(hdev))
3978 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3979 MGMT_STATUS_REJECTED);
3980
3981 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3982 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3983 return cmd_status(sk, hdev->id,
3984 MGMT_OP_SET_STATIC_ADDRESS,
3985 MGMT_STATUS_INVALID_PARAMS);
3986
3987 /* Two most significant bits shall be set */
3988 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3989 return cmd_status(sk, hdev->id,
3990 MGMT_OP_SET_STATIC_ADDRESS,
3991 MGMT_STATUS_INVALID_PARAMS);
3992 }
3993
3994 hci_dev_lock(hdev);
3995
3996 bacpy(&hdev->static_addr, &cp->bdaddr);
3997
3998 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3999
4000 hci_dev_unlock(hdev);
4001
4002 return err;
4003}
4004
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004005static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4006 void *data, u16 len)
4007{
4008 struct mgmt_cp_set_scan_params *cp = data;
4009 __u16 interval, window;
4010 int err;
4011
4012 BT_DBG("%s", hdev->name);
4013
4014 if (!lmp_le_capable(hdev))
4015 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4016 MGMT_STATUS_NOT_SUPPORTED);
4017
4018 interval = __le16_to_cpu(cp->interval);
4019
4020 if (interval < 0x0004 || interval > 0x4000)
4021 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4022 MGMT_STATUS_INVALID_PARAMS);
4023
4024 window = __le16_to_cpu(cp->window);
4025
4026 if (window < 0x0004 || window > 0x4000)
4027 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4028 MGMT_STATUS_INVALID_PARAMS);
4029
Marcel Holtmann899e1072013-10-14 09:55:32 -07004030 if (window > interval)
4031 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4032 MGMT_STATUS_INVALID_PARAMS);
4033
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004034 hci_dev_lock(hdev);
4035
4036 hdev->le_scan_interval = interval;
4037 hdev->le_scan_window = window;
4038
4039 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4040
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004041 /* If background scan is running, restart it so new parameters are
4042 * loaded.
4043 */
4044 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4045 hdev->discovery.state == DISCOVERY_STOPPED) {
4046 struct hci_request req;
4047
4048 hci_req_init(&req, hdev);
4049
4050 hci_req_add_le_scan_disable(&req);
4051 hci_req_add_le_passive_scan(&req);
4052
4053 hci_req_run(&req, NULL);
4054 }
4055
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004056 hci_dev_unlock(hdev);
4057
4058 return err;
4059}
4060
Johan Hedberg33e38b32013-03-15 17:07:05 -05004061static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4062{
4063 struct pending_cmd *cmd;
4064
4065 BT_DBG("status 0x%02x", status);
4066
4067 hci_dev_lock(hdev);
4068
4069 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4070 if (!cmd)
4071 goto unlock;
4072
4073 if (status) {
4074 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4075 mgmt_status(status));
4076 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004077 struct mgmt_mode *cp = cmd->param;
4078
4079 if (cp->val)
4080 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4081 else
4082 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4083
Johan Hedberg33e38b32013-03-15 17:07:05 -05004084 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4085 new_settings(hdev, cmd->sk);
4086 }
4087
4088 mgmt_pending_remove(cmd);
4089
4090unlock:
4091 hci_dev_unlock(hdev);
4092}
4093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004094static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004095 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004096{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004097 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004098 struct pending_cmd *cmd;
4099 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004100 int err;
4101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004102 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004103
Johan Hedberg56f87902013-10-02 13:43:13 +03004104 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4105 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004106 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4107 MGMT_STATUS_NOT_SUPPORTED);
4108
Johan Hedberga7e80f22013-01-09 16:05:19 +02004109 if (cp->val != 0x00 && cp->val != 0x01)
4110 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4111 MGMT_STATUS_INVALID_PARAMS);
4112
Johan Hedberg5400c042012-02-21 16:40:33 +02004113 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004114 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004115 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004116
4117 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004118 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004119 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004120
4121 hci_dev_lock(hdev);
4122
Johan Hedberg05cbf292013-03-15 17:07:07 -05004123 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4124 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4125 MGMT_STATUS_BUSY);
4126 goto unlock;
4127 }
4128
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004129 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4130 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4131 hdev);
4132 goto unlock;
4133 }
4134
Johan Hedberg33e38b32013-03-15 17:07:05 -05004135 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4136 data, len);
4137 if (!cmd) {
4138 err = -ENOMEM;
4139 goto unlock;
4140 }
4141
4142 hci_req_init(&req, hdev);
4143
Johan Hedberg406d7802013-03-15 17:07:09 -05004144 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004145
4146 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004147 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004148 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004149 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004150 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004151 }
4152
Johan Hedberg33e38b32013-03-15 17:07:05 -05004153unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004154 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004155
Antti Julkuf6422ec2011-06-22 13:11:56 +03004156 return err;
4157}
4158
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004159static void set_bredr_scan(struct hci_request *req)
4160{
4161 struct hci_dev *hdev = req->hdev;
4162 u8 scan = 0;
4163
4164 /* Ensure that fast connectable is disabled. This function will
4165 * not do anything if the page scan parameters are already what
4166 * they should be.
4167 */
4168 write_fast_connectable(req, false);
4169
4170 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4171 scan |= SCAN_PAGE;
4172 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4173 scan |= SCAN_INQUIRY;
4174
4175 if (scan)
4176 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4177}
4178
Johan Hedberg0663ca22013-10-02 13:43:14 +03004179static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4180{
4181 struct pending_cmd *cmd;
4182
4183 BT_DBG("status 0x%02x", status);
4184
4185 hci_dev_lock(hdev);
4186
4187 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4188 if (!cmd)
4189 goto unlock;
4190
4191 if (status) {
4192 u8 mgmt_err = mgmt_status(status);
4193
4194 /* We need to restore the flag if related HCI commands
4195 * failed.
4196 */
4197 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4198
4199 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4200 } else {
4201 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4202 new_settings(hdev, cmd->sk);
4203 }
4204
4205 mgmt_pending_remove(cmd);
4206
4207unlock:
4208 hci_dev_unlock(hdev);
4209}
4210
4211static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4212{
4213 struct mgmt_mode *cp = data;
4214 struct pending_cmd *cmd;
4215 struct hci_request req;
4216 int err;
4217
4218 BT_DBG("request for %s", hdev->name);
4219
4220 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4221 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4222 MGMT_STATUS_NOT_SUPPORTED);
4223
4224 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4225 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4226 MGMT_STATUS_REJECTED);
4227
4228 if (cp->val != 0x00 && cp->val != 0x01)
4229 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4230 MGMT_STATUS_INVALID_PARAMS);
4231
4232 hci_dev_lock(hdev);
4233
4234 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4235 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4236 goto unlock;
4237 }
4238
4239 if (!hdev_is_powered(hdev)) {
4240 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004241 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4242 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4243 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4244 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4245 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4246 }
4247
4248 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4249
4250 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4251 if (err < 0)
4252 goto unlock;
4253
4254 err = new_settings(hdev, sk);
4255 goto unlock;
4256 }
4257
4258 /* Reject disabling when powered on */
4259 if (!cp->val) {
4260 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4261 MGMT_STATUS_REJECTED);
4262 goto unlock;
4263 }
4264
4265 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4266 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4267 MGMT_STATUS_BUSY);
4268 goto unlock;
4269 }
4270
4271 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4272 if (!cmd) {
4273 err = -ENOMEM;
4274 goto unlock;
4275 }
4276
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004277 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004278 * generates the correct flags.
4279 */
4280 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4281
4282 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004283
4284 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4285 set_bredr_scan(&req);
4286
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004287 /* Since only the advertising data flags will change, there
4288 * is no need to update the scan response data.
4289 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004290 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004291
Johan Hedberg0663ca22013-10-02 13:43:14 +03004292 err = hci_req_run(&req, set_bredr_complete);
4293 if (err < 0)
4294 mgmt_pending_remove(cmd);
4295
4296unlock:
4297 hci_dev_unlock(hdev);
4298 return err;
4299}
4300
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004301static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4302 void *data, u16 len)
4303{
4304 struct mgmt_mode *cp = data;
4305 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004306 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004307 int err;
4308
4309 BT_DBG("request for %s", hdev->name);
4310
4311 status = mgmt_bredr_support(hdev);
4312 if (status)
4313 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4314 status);
4315
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004316 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004317 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004318 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4319 MGMT_STATUS_NOT_SUPPORTED);
4320
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004321 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004322 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4323 MGMT_STATUS_INVALID_PARAMS);
4324
4325 hci_dev_lock(hdev);
4326
4327 if (!hdev_is_powered(hdev)) {
4328 bool changed;
4329
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004330 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004331 changed = !test_and_set_bit(HCI_SC_ENABLED,
4332 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004333 if (cp->val == 0x02)
4334 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4335 else
4336 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4337 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004338 changed = test_and_clear_bit(HCI_SC_ENABLED,
4339 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004340 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4341 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004342
4343 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4344 if (err < 0)
4345 goto failed;
4346
4347 if (changed)
4348 err = new_settings(hdev, sk);
4349
4350 goto failed;
4351 }
4352
4353 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4354 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4355 MGMT_STATUS_BUSY);
4356 goto failed;
4357 }
4358
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004359 val = !!cp->val;
4360
4361 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4362 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004363 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4364 goto failed;
4365 }
4366
4367 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4368 if (!cmd) {
4369 err = -ENOMEM;
4370 goto failed;
4371 }
4372
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004373 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004374 if (err < 0) {
4375 mgmt_pending_remove(cmd);
4376 goto failed;
4377 }
4378
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004379 if (cp->val == 0x02)
4380 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4381 else
4382 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4383
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004384failed:
4385 hci_dev_unlock(hdev);
4386 return err;
4387}
4388
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004389static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4390 void *data, u16 len)
4391{
4392 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004393 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004394 int err;
4395
4396 BT_DBG("request for %s", hdev->name);
4397
Johan Hedbergb97109792014-06-24 14:00:28 +03004398 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004399 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4400 MGMT_STATUS_INVALID_PARAMS);
4401
4402 hci_dev_lock(hdev);
4403
4404 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004405 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4406 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004407 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004408 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4409 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004410
Johan Hedbergb97109792014-06-24 14:00:28 +03004411 if (cp->val == 0x02)
4412 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4413 &hdev->dev_flags);
4414 else
4415 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4416 &hdev->dev_flags);
4417
4418 if (hdev_is_powered(hdev) && use_changed &&
4419 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4420 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4421 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4422 sizeof(mode), &mode);
4423 }
4424
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004425 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4426 if (err < 0)
4427 goto unlock;
4428
4429 if (changed)
4430 err = new_settings(hdev, sk);
4431
4432unlock:
4433 hci_dev_unlock(hdev);
4434 return err;
4435}
4436
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004437static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4438 u16 len)
4439{
4440 struct mgmt_cp_set_privacy *cp = cp_data;
4441 bool changed;
4442 int err;
4443
4444 BT_DBG("request for %s", hdev->name);
4445
4446 if (!lmp_le_capable(hdev))
4447 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4448 MGMT_STATUS_NOT_SUPPORTED);
4449
4450 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4451 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4452 MGMT_STATUS_INVALID_PARAMS);
4453
4454 if (hdev_is_powered(hdev))
4455 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4456 MGMT_STATUS_REJECTED);
4457
4458 hci_dev_lock(hdev);
4459
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004460 /* If user space supports this command it is also expected to
4461 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4462 */
4463 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4464
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004465 if (cp->privacy) {
4466 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4467 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4468 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4469 } else {
4470 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4471 memset(hdev->irk, 0, sizeof(hdev->irk));
4472 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4473 }
4474
4475 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4476 if (err < 0)
4477 goto unlock;
4478
4479 if (changed)
4480 err = new_settings(hdev, sk);
4481
4482unlock:
4483 hci_dev_unlock(hdev);
4484 return err;
4485}
4486
Johan Hedberg41edf162014-02-18 10:19:35 +02004487static bool irk_is_valid(struct mgmt_irk_info *irk)
4488{
4489 switch (irk->addr.type) {
4490 case BDADDR_LE_PUBLIC:
4491 return true;
4492
4493 case BDADDR_LE_RANDOM:
4494 /* Two most significant bits shall be set */
4495 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4496 return false;
4497 return true;
4498 }
4499
4500 return false;
4501}
4502
4503static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4504 u16 len)
4505{
4506 struct mgmt_cp_load_irks *cp = cp_data;
4507 u16 irk_count, expected_len;
4508 int i, err;
4509
4510 BT_DBG("request for %s", hdev->name);
4511
4512 if (!lmp_le_capable(hdev))
4513 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4514 MGMT_STATUS_NOT_SUPPORTED);
4515
4516 irk_count = __le16_to_cpu(cp->irk_count);
4517
4518 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4519 if (expected_len != len) {
4520 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004521 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004522 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4523 MGMT_STATUS_INVALID_PARAMS);
4524 }
4525
4526 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4527
4528 for (i = 0; i < irk_count; i++) {
4529 struct mgmt_irk_info *key = &cp->irks[i];
4530
4531 if (!irk_is_valid(key))
4532 return cmd_status(sk, hdev->id,
4533 MGMT_OP_LOAD_IRKS,
4534 MGMT_STATUS_INVALID_PARAMS);
4535 }
4536
4537 hci_dev_lock(hdev);
4538
4539 hci_smp_irks_clear(hdev);
4540
4541 for (i = 0; i < irk_count; i++) {
4542 struct mgmt_irk_info *irk = &cp->irks[i];
4543 u8 addr_type;
4544
4545 if (irk->addr.type == BDADDR_LE_PUBLIC)
4546 addr_type = ADDR_LE_DEV_PUBLIC;
4547 else
4548 addr_type = ADDR_LE_DEV_RANDOM;
4549
4550 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4551 BDADDR_ANY);
4552 }
4553
4554 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4555
4556 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4557
4558 hci_dev_unlock(hdev);
4559
4560 return err;
4561}
4562
Johan Hedberg3f706b72013-01-20 14:27:16 +02004563static bool ltk_is_valid(struct mgmt_ltk_info *key)
4564{
4565 if (key->master != 0x00 && key->master != 0x01)
4566 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004567
4568 switch (key->addr.type) {
4569 case BDADDR_LE_PUBLIC:
4570 return true;
4571
4572 case BDADDR_LE_RANDOM:
4573 /* Two most significant bits shall be set */
4574 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4575 return false;
4576 return true;
4577 }
4578
4579 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004580}
4581
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004582static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004583 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004584{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004585 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4586 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004587 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004588
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004589 BT_DBG("request for %s", hdev->name);
4590
4591 if (!lmp_le_capable(hdev))
4592 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4593 MGMT_STATUS_NOT_SUPPORTED);
4594
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004595 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004596
4597 expected_len = sizeof(*cp) + key_count *
4598 sizeof(struct mgmt_ltk_info);
4599 if (expected_len != len) {
4600 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004601 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004602 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004603 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004604 }
4605
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004606 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004607
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004608 for (i = 0; i < key_count; i++) {
4609 struct mgmt_ltk_info *key = &cp->keys[i];
4610
Johan Hedberg3f706b72013-01-20 14:27:16 +02004611 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004612 return cmd_status(sk, hdev->id,
4613 MGMT_OP_LOAD_LONG_TERM_KEYS,
4614 MGMT_STATUS_INVALID_PARAMS);
4615 }
4616
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004617 hci_dev_lock(hdev);
4618
4619 hci_smp_ltks_clear(hdev);
4620
4621 for (i = 0; i < key_count; i++) {
4622 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004623 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004624
4625 if (key->addr.type == BDADDR_LE_PUBLIC)
4626 addr_type = ADDR_LE_DEV_PUBLIC;
4627 else
4628 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004629
4630 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004631 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004632 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004633 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004634
Johan Hedberg61b43352014-05-29 19:36:53 +03004635 switch (key->type) {
4636 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004637 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004638 break;
4639 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004640 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004641 break;
4642 default:
4643 continue;
4644 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004645
Johan Hedberg35d70272014-02-19 14:57:47 +02004646 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004647 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004648 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004649 }
4650
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004651 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4652 NULL, 0);
4653
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004654 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004655
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004656 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004657}
4658
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004659struct cmd_conn_lookup {
4660 struct hci_conn *conn;
4661 bool valid_tx_power;
4662 u8 mgmt_status;
4663};
4664
4665static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4666{
4667 struct cmd_conn_lookup *match = data;
4668 struct mgmt_cp_get_conn_info *cp;
4669 struct mgmt_rp_get_conn_info rp;
4670 struct hci_conn *conn = cmd->user_data;
4671
4672 if (conn != match->conn)
4673 return;
4674
4675 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4676
4677 memset(&rp, 0, sizeof(rp));
4678 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4679 rp.addr.type = cp->addr.type;
4680
4681 if (!match->mgmt_status) {
4682 rp.rssi = conn->rssi;
4683
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004684 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004685 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004686 rp.max_tx_power = conn->max_tx_power;
4687 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004688 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004689 rp.max_tx_power = HCI_TX_POWER_INVALID;
4690 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004691 }
4692
4693 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4694 match->mgmt_status, &rp, sizeof(rp));
4695
4696 hci_conn_drop(conn);
4697
4698 mgmt_pending_remove(cmd);
4699}
4700
4701static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4702{
4703 struct hci_cp_read_rssi *cp;
4704 struct hci_conn *conn;
4705 struct cmd_conn_lookup match;
4706 u16 handle;
4707
4708 BT_DBG("status 0x%02x", status);
4709
4710 hci_dev_lock(hdev);
4711
4712 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004713 * otherwise we assume it's not valid. At the moment we assume that
4714 * either both or none of current and max values are valid to keep code
4715 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004716 */
4717 match.valid_tx_power = !status;
4718
4719 /* Commands sent in request are either Read RSSI or Read Transmit Power
4720 * Level so we check which one was last sent to retrieve connection
4721 * handle. Both commands have handle as first parameter so it's safe to
4722 * cast data on the same command struct.
4723 *
4724 * First command sent is always Read RSSI and we fail only if it fails.
4725 * In other case we simply override error to indicate success as we
4726 * already remembered if TX power value is actually valid.
4727 */
4728 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4729 if (!cp) {
4730 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4731 status = 0;
4732 }
4733
4734 if (!cp) {
4735 BT_ERR("invalid sent_cmd in response");
4736 goto unlock;
4737 }
4738
4739 handle = __le16_to_cpu(cp->handle);
4740 conn = hci_conn_hash_lookup_handle(hdev, handle);
4741 if (!conn) {
4742 BT_ERR("unknown handle (%d) in response", handle);
4743 goto unlock;
4744 }
4745
4746 match.conn = conn;
4747 match.mgmt_status = mgmt_status(status);
4748
4749 /* Cache refresh is complete, now reply for mgmt request for given
4750 * connection only.
4751 */
4752 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4753 get_conn_info_complete, &match);
4754
4755unlock:
4756 hci_dev_unlock(hdev);
4757}
4758
4759static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4760 u16 len)
4761{
4762 struct mgmt_cp_get_conn_info *cp = data;
4763 struct mgmt_rp_get_conn_info rp;
4764 struct hci_conn *conn;
4765 unsigned long conn_info_age;
4766 int err = 0;
4767
4768 BT_DBG("%s", hdev->name);
4769
4770 memset(&rp, 0, sizeof(rp));
4771 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4772 rp.addr.type = cp->addr.type;
4773
4774 if (!bdaddr_type_is_valid(cp->addr.type))
4775 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4776 MGMT_STATUS_INVALID_PARAMS,
4777 &rp, sizeof(rp));
4778
4779 hci_dev_lock(hdev);
4780
4781 if (!hdev_is_powered(hdev)) {
4782 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4783 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4784 goto unlock;
4785 }
4786
4787 if (cp->addr.type == BDADDR_BREDR)
4788 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4789 &cp->addr.bdaddr);
4790 else
4791 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4792
4793 if (!conn || conn->state != BT_CONNECTED) {
4794 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4795 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4796 goto unlock;
4797 }
4798
4799 /* To avoid client trying to guess when to poll again for information we
4800 * calculate conn info age as random value between min/max set in hdev.
4801 */
4802 conn_info_age = hdev->conn_info_min_age +
4803 prandom_u32_max(hdev->conn_info_max_age -
4804 hdev->conn_info_min_age);
4805
4806 /* Query controller to refresh cached values if they are too old or were
4807 * never read.
4808 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004809 if (time_after(jiffies, conn->conn_info_timestamp +
4810 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004811 !conn->conn_info_timestamp) {
4812 struct hci_request req;
4813 struct hci_cp_read_tx_power req_txp_cp;
4814 struct hci_cp_read_rssi req_rssi_cp;
4815 struct pending_cmd *cmd;
4816
4817 hci_req_init(&req, hdev);
4818 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4819 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4820 &req_rssi_cp);
4821
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004822 /* For LE links TX power does not change thus we don't need to
4823 * query for it once value is known.
4824 */
4825 if (!bdaddr_type_is_le(cp->addr.type) ||
4826 conn->tx_power == HCI_TX_POWER_INVALID) {
4827 req_txp_cp.handle = cpu_to_le16(conn->handle);
4828 req_txp_cp.type = 0x00;
4829 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4830 sizeof(req_txp_cp), &req_txp_cp);
4831 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004832
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004833 /* Max TX power needs to be read only once per connection */
4834 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4835 req_txp_cp.handle = cpu_to_le16(conn->handle);
4836 req_txp_cp.type = 0x01;
4837 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4838 sizeof(req_txp_cp), &req_txp_cp);
4839 }
4840
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004841 err = hci_req_run(&req, conn_info_refresh_complete);
4842 if (err < 0)
4843 goto unlock;
4844
4845 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4846 data, len);
4847 if (!cmd) {
4848 err = -ENOMEM;
4849 goto unlock;
4850 }
4851
4852 hci_conn_hold(conn);
4853 cmd->user_data = conn;
4854
4855 conn->conn_info_timestamp = jiffies;
4856 } else {
4857 /* Cache is valid, just reply with values cached in hci_conn */
4858 rp.rssi = conn->rssi;
4859 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004860 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004861
4862 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4863 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4864 }
4865
4866unlock:
4867 hci_dev_unlock(hdev);
4868 return err;
4869}
4870
Johan Hedberg95868422014-06-28 17:54:07 +03004871static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4872{
4873 struct mgmt_cp_get_clock_info *cp;
4874 struct mgmt_rp_get_clock_info rp;
4875 struct hci_cp_read_clock *hci_cp;
4876 struct pending_cmd *cmd;
4877 struct hci_conn *conn;
4878
4879 BT_DBG("%s status %u", hdev->name, status);
4880
4881 hci_dev_lock(hdev);
4882
4883 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4884 if (!hci_cp)
4885 goto unlock;
4886
4887 if (hci_cp->which) {
4888 u16 handle = __le16_to_cpu(hci_cp->handle);
4889 conn = hci_conn_hash_lookup_handle(hdev, handle);
4890 } else {
4891 conn = NULL;
4892 }
4893
4894 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4895 if (!cmd)
4896 goto unlock;
4897
4898 cp = cmd->param;
4899
4900 memset(&rp, 0, sizeof(rp));
4901 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4902
4903 if (status)
4904 goto send_rsp;
4905
4906 rp.local_clock = cpu_to_le32(hdev->clock);
4907
4908 if (conn) {
4909 rp.piconet_clock = cpu_to_le32(conn->clock);
4910 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4911 }
4912
4913send_rsp:
4914 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4915 &rp, sizeof(rp));
4916 mgmt_pending_remove(cmd);
4917 if (conn)
4918 hci_conn_drop(conn);
4919
4920unlock:
4921 hci_dev_unlock(hdev);
4922}
4923
4924static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4925 u16 len)
4926{
4927 struct mgmt_cp_get_clock_info *cp = data;
4928 struct mgmt_rp_get_clock_info rp;
4929 struct hci_cp_read_clock hci_cp;
4930 struct pending_cmd *cmd;
4931 struct hci_request req;
4932 struct hci_conn *conn;
4933 int err;
4934
4935 BT_DBG("%s", hdev->name);
4936
4937 memset(&rp, 0, sizeof(rp));
4938 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4939 rp.addr.type = cp->addr.type;
4940
4941 if (cp->addr.type != BDADDR_BREDR)
4942 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4943 MGMT_STATUS_INVALID_PARAMS,
4944 &rp, sizeof(rp));
4945
4946 hci_dev_lock(hdev);
4947
4948 if (!hdev_is_powered(hdev)) {
4949 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4950 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4951 goto unlock;
4952 }
4953
4954 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4955 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4956 &cp->addr.bdaddr);
4957 if (!conn || conn->state != BT_CONNECTED) {
4958 err = cmd_complete(sk, hdev->id,
4959 MGMT_OP_GET_CLOCK_INFO,
4960 MGMT_STATUS_NOT_CONNECTED,
4961 &rp, sizeof(rp));
4962 goto unlock;
4963 }
4964 } else {
4965 conn = NULL;
4966 }
4967
4968 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4969 if (!cmd) {
4970 err = -ENOMEM;
4971 goto unlock;
4972 }
4973
4974 hci_req_init(&req, hdev);
4975
4976 memset(&hci_cp, 0, sizeof(hci_cp));
4977 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4978
4979 if (conn) {
4980 hci_conn_hold(conn);
4981 cmd->user_data = conn;
4982
4983 hci_cp.handle = cpu_to_le16(conn->handle);
4984 hci_cp.which = 0x01; /* Piconet clock */
4985 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4986 }
4987
4988 err = hci_req_run(&req, get_clock_info_complete);
4989 if (err < 0)
4990 mgmt_pending_remove(cmd);
4991
4992unlock:
4993 hci_dev_unlock(hdev);
4994 return err;
4995}
4996
Marcel Holtmann8afef092014-06-29 22:28:34 +02004997static void device_added(struct sock *sk, struct hci_dev *hdev,
4998 bdaddr_t *bdaddr, u8 type, u8 action)
4999{
5000 struct mgmt_ev_device_added ev;
5001
5002 bacpy(&ev.addr.bdaddr, bdaddr);
5003 ev.addr.type = type;
5004 ev.action = action;
5005
5006 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5007}
5008
Marcel Holtmann2faade52014-06-29 19:44:03 +02005009static int add_device(struct sock *sk, struct hci_dev *hdev,
5010 void *data, u16 len)
5011{
5012 struct mgmt_cp_add_device *cp = data;
5013 u8 auto_conn, addr_type;
5014 int err;
5015
5016 BT_DBG("%s", hdev->name);
5017
5018 if (!bdaddr_type_is_le(cp->addr.type) ||
5019 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5020 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5021 MGMT_STATUS_INVALID_PARAMS,
5022 &cp->addr, sizeof(cp->addr));
5023
5024 if (cp->action != 0x00 && cp->action != 0x01)
5025 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5026 MGMT_STATUS_INVALID_PARAMS,
5027 &cp->addr, sizeof(cp->addr));
5028
5029 hci_dev_lock(hdev);
5030
5031 if (cp->addr.type == BDADDR_LE_PUBLIC)
5032 addr_type = ADDR_LE_DEV_PUBLIC;
5033 else
5034 addr_type = ADDR_LE_DEV_RANDOM;
5035
5036 if (cp->action)
5037 auto_conn = HCI_AUTO_CONN_ALWAYS;
5038 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005039 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005040
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005041 /* If the connection parameters don't exist for this device,
5042 * they will be created and configured with defaults.
5043 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005044 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5045 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005046 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5047 MGMT_STATUS_FAILED,
5048 &cp->addr, sizeof(cp->addr));
5049 goto unlock;
5050 }
5051
Marcel Holtmann8afef092014-06-29 22:28:34 +02005052 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5053
Marcel Holtmann2faade52014-06-29 19:44:03 +02005054 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5055 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5056
5057unlock:
5058 hci_dev_unlock(hdev);
5059 return err;
5060}
5061
Marcel Holtmann8afef092014-06-29 22:28:34 +02005062static void device_removed(struct sock *sk, struct hci_dev *hdev,
5063 bdaddr_t *bdaddr, u8 type)
5064{
5065 struct mgmt_ev_device_removed ev;
5066
5067 bacpy(&ev.addr.bdaddr, bdaddr);
5068 ev.addr.type = type;
5069
5070 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5071}
5072
Marcel Holtmann2faade52014-06-29 19:44:03 +02005073static int remove_device(struct sock *sk, struct hci_dev *hdev,
5074 void *data, u16 len)
5075{
5076 struct mgmt_cp_remove_device *cp = data;
5077 int err;
5078
5079 BT_DBG("%s", hdev->name);
5080
5081 hci_dev_lock(hdev);
5082
5083 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005084 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005085 u8 addr_type;
5086
5087 if (!bdaddr_type_is_le(cp->addr.type)) {
5088 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5089 MGMT_STATUS_INVALID_PARAMS,
5090 &cp->addr, sizeof(cp->addr));
5091 goto unlock;
5092 }
5093
5094 if (cp->addr.type == BDADDR_LE_PUBLIC)
5095 addr_type = ADDR_LE_DEV_PUBLIC;
5096 else
5097 addr_type = ADDR_LE_DEV_RANDOM;
5098
Johan Hedbergc71593d2014-07-02 17:37:28 +03005099 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5100 addr_type);
5101 if (!params) {
5102 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5103 MGMT_STATUS_INVALID_PARAMS,
5104 &cp->addr, sizeof(cp->addr));
5105 goto unlock;
5106 }
5107
5108 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5109 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5110 MGMT_STATUS_INVALID_PARAMS,
5111 &cp->addr, sizeof(cp->addr));
5112 goto unlock;
5113 }
5114
5115 hci_pend_le_conn_del(hdev, &cp->addr.bdaddr, addr_type);
5116 list_del(&params->list);
5117 kfree(params);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005118
5119 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005120 } else {
5121 if (cp->addr.type) {
5122 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5123 MGMT_STATUS_INVALID_PARAMS,
5124 &cp->addr, sizeof(cp->addr));
5125 goto unlock;
5126 }
5127
Johan Hedbergc71593d2014-07-02 17:37:28 +03005128 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005129 }
5130
5131 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5132 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5133
5134unlock:
5135 hci_dev_unlock(hdev);
5136 return err;
5137}
5138
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005139static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5140 u16 len)
5141{
5142 struct mgmt_cp_load_conn_param *cp = data;
5143 u16 param_count, expected_len;
5144 int i;
5145
5146 if (!lmp_le_capable(hdev))
5147 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5148 MGMT_STATUS_NOT_SUPPORTED);
5149
5150 param_count = __le16_to_cpu(cp->param_count);
5151
5152 expected_len = sizeof(*cp) + param_count *
5153 sizeof(struct mgmt_conn_param);
5154 if (expected_len != len) {
5155 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5156 expected_len, len);
5157 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5158 MGMT_STATUS_INVALID_PARAMS);
5159 }
5160
5161 BT_DBG("%s param_count %u", hdev->name, param_count);
5162
5163 hci_dev_lock(hdev);
5164
5165 hci_conn_params_clear_disabled(hdev);
5166
5167 for (i = 0; i < param_count; i++) {
5168 struct mgmt_conn_param *param = &cp->params[i];
5169 struct hci_conn_params *hci_param;
5170 u16 min, max, latency, timeout;
5171 u8 addr_type;
5172
5173 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5174 param->addr.type);
5175
5176 if (param->addr.type == BDADDR_LE_PUBLIC) {
5177 addr_type = ADDR_LE_DEV_PUBLIC;
5178 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5179 addr_type = ADDR_LE_DEV_RANDOM;
5180 } else {
5181 BT_ERR("Ignoring invalid connection parameters");
5182 continue;
5183 }
5184
5185 min = le16_to_cpu(param->min_interval);
5186 max = le16_to_cpu(param->max_interval);
5187 latency = le16_to_cpu(param->latency);
5188 timeout = le16_to_cpu(param->timeout);
5189
5190 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5191 min, max, latency, timeout);
5192
5193 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5194 BT_ERR("Ignoring invalid connection parameters");
5195 continue;
5196 }
5197
5198 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5199 addr_type);
5200 if (!hci_param) {
5201 BT_ERR("Failed to add connection parameters");
5202 continue;
5203 }
5204
5205 hci_param->conn_min_interval = min;
5206 hci_param->conn_max_interval = max;
5207 hci_param->conn_latency = latency;
5208 hci_param->supervision_timeout = timeout;
5209 }
5210
5211 hci_dev_unlock(hdev);
5212
5213 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5214}
5215
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005216static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005217 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5218 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005219 bool var_len;
5220 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005221} mgmt_handlers[] = {
5222 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005223 { read_version, false, MGMT_READ_VERSION_SIZE },
5224 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5225 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5226 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5227 { set_powered, false, MGMT_SETTING_SIZE },
5228 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5229 { set_connectable, false, MGMT_SETTING_SIZE },
5230 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5231 { set_pairable, false, MGMT_SETTING_SIZE },
5232 { set_link_security, false, MGMT_SETTING_SIZE },
5233 { set_ssp, false, MGMT_SETTING_SIZE },
5234 { set_hs, false, MGMT_SETTING_SIZE },
5235 { set_le, false, MGMT_SETTING_SIZE },
5236 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5237 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5238 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5239 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5240 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5241 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5242 { disconnect, false, MGMT_DISCONNECT_SIZE },
5243 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5244 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5245 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5246 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5247 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5248 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5249 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5250 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5251 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5252 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5253 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5254 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005255 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005256 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5257 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5258 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5259 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5260 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5261 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005262 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005263 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005264 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005265 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005266 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005267 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005268 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005269 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005270 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005271 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005272 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005273 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5274 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005275 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005276};
5277
Johan Hedberg03811012010-12-08 00:21:06 +02005278int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5279{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005280 void *buf;
5281 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005282 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005283 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005284 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005285 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005286 int err;
5287
5288 BT_DBG("got %zu bytes", msglen);
5289
5290 if (msglen < sizeof(*hdr))
5291 return -EINVAL;
5292
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005293 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005294 if (!buf)
5295 return -ENOMEM;
5296
5297 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5298 err = -EFAULT;
5299 goto done;
5300 }
5301
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005302 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005303 opcode = __le16_to_cpu(hdr->opcode);
5304 index = __le16_to_cpu(hdr->index);
5305 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005306
5307 if (len != msglen - sizeof(*hdr)) {
5308 err = -EINVAL;
5309 goto done;
5310 }
5311
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005312 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005313 hdev = hci_dev_get(index);
5314 if (!hdev) {
5315 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005316 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005317 goto done;
5318 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005319
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005320 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005321 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5322 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005323 err = cmd_status(sk, index, opcode,
5324 MGMT_STATUS_INVALID_INDEX);
5325 goto done;
5326 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005327 }
5328
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005329 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005330 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005331 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005332 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005333 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005334 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005335 }
5336
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005337 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005338 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005339 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005340 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005341 goto done;
5342 }
5343
Johan Hedbergbe22b542012-03-01 22:24:41 +02005344 handler = &mgmt_handlers[opcode];
5345
5346 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005347 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005348 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005349 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005350 goto done;
5351 }
5352
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005353 if (hdev)
5354 mgmt_init_hdev(sk, hdev);
5355
5356 cp = buf + sizeof(*hdr);
5357
Johan Hedbergbe22b542012-03-01 22:24:41 +02005358 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005359 if (err < 0)
5360 goto done;
5361
Johan Hedberg03811012010-12-08 00:21:06 +02005362 err = msglen;
5363
5364done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005365 if (hdev)
5366 hci_dev_put(hdev);
5367
Johan Hedberg03811012010-12-08 00:21:06 +02005368 kfree(buf);
5369 return err;
5370}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005371
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005372void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005373{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005374 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005375 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005376
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005377 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5378 return;
5379
5380 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5381 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5382 else
5383 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005384}
5385
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005386void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005387{
Johan Hedberg5f159032012-03-02 03:13:19 +02005388 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005389
Marcel Holtmann1514b892013-10-06 08:25:01 -07005390 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005391 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005392
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005393 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5394 return;
5395
Johan Hedberg744cf192011-11-08 20:40:14 +02005396 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005397
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005398 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005399}
5400
Andre Guedes6046dc32014-02-26 20:21:51 -03005401/* This function requires the caller holds hdev->lock */
5402static void restart_le_auto_conns(struct hci_dev *hdev)
5403{
5404 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005405 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005406
5407 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005408 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005409 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005410 added = true;
5411 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005412 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005413
5414 /* Calling hci_pend_le_conn_add will actually already trigger
5415 * background scanning when needed. So no need to trigger it
5416 * just another time.
5417 *
5418 * This check is here to avoid an unneeded restart of the
5419 * passive scanning. Since this is during the controller
5420 * power up phase the duplicate filtering is not an issue.
5421 */
5422 if (added)
5423 return;
5424
5425 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005426}
5427
Johan Hedberg229ab392013-03-15 17:06:53 -05005428static void powered_complete(struct hci_dev *hdev, u8 status)
5429{
5430 struct cmd_lookup match = { NULL, hdev };
5431
5432 BT_DBG("status 0x%02x", status);
5433
5434 hci_dev_lock(hdev);
5435
Andre Guedes6046dc32014-02-26 20:21:51 -03005436 restart_le_auto_conns(hdev);
5437
Johan Hedberg229ab392013-03-15 17:06:53 -05005438 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5439
5440 new_settings(hdev, match.sk);
5441
5442 hci_dev_unlock(hdev);
5443
5444 if (match.sk)
5445 sock_put(match.sk);
5446}
5447
Johan Hedberg70da6242013-03-15 17:06:51 -05005448static int powered_update_hci(struct hci_dev *hdev)
5449{
Johan Hedberg890ea892013-03-15 17:06:52 -05005450 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005451 u8 link_sec;
5452
Johan Hedberg890ea892013-03-15 17:06:52 -05005453 hci_req_init(&req, hdev);
5454
Johan Hedberg70da6242013-03-15 17:06:51 -05005455 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5456 !lmp_host_ssp_capable(hdev)) {
5457 u8 ssp = 1;
5458
Johan Hedberg890ea892013-03-15 17:06:52 -05005459 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005460 }
5461
Johan Hedbergc73eee92013-04-19 18:35:21 +03005462 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5463 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005464 struct hci_cp_write_le_host_supported cp;
5465
5466 cp.le = 1;
5467 cp.simul = lmp_le_br_capable(hdev);
5468
5469 /* Check first if we already have the right
5470 * host state (host features set)
5471 */
5472 if (cp.le != lmp_host_le_capable(hdev) ||
5473 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005474 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5475 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005476 }
5477
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005478 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005479 /* Make sure the controller has a good default for
5480 * advertising data. This also applies to the case
5481 * where BR/EDR was toggled during the AUTO_OFF phase.
5482 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005483 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005484 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005485 update_scan_rsp_data(&req);
5486 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005487
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005488 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5489 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005490 }
5491
Johan Hedberg70da6242013-03-15 17:06:51 -05005492 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5493 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005494 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5495 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005496
5497 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005498 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5499 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005500 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005501 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005502 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005503 }
5504
Johan Hedberg229ab392013-03-15 17:06:53 -05005505 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005506}
5507
Johan Hedberg744cf192011-11-08 20:40:14 +02005508int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005509{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005510 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005511 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5512 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005513 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005514
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005515 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5516 return 0;
5517
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005518 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005519 if (powered_update_hci(hdev) == 0)
5520 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005521
Johan Hedberg229ab392013-03-15 17:06:53 -05005522 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5523 &match);
5524 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005525 }
5526
Johan Hedberg229ab392013-03-15 17:06:53 -05005527 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5528 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5529
5530 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5531 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5532 zero_cod, sizeof(zero_cod), NULL);
5533
5534new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005535 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005536
5537 if (match.sk)
5538 sock_put(match.sk);
5539
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005540 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005541}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005542
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005543void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005544{
5545 struct pending_cmd *cmd;
5546 u8 status;
5547
5548 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5549 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005550 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005551
5552 if (err == -ERFKILL)
5553 status = MGMT_STATUS_RFKILLED;
5554 else
5555 status = MGMT_STATUS_FAILED;
5556
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005557 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005558
5559 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005560}
5561
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005562void mgmt_discoverable_timeout(struct hci_dev *hdev)
5563{
5564 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005565
5566 hci_dev_lock(hdev);
5567
5568 /* When discoverable timeout triggers, then just make sure
5569 * the limited discoverable flag is cleared. Even in the case
5570 * of a timeout triggered from general discoverable, it is
5571 * safe to unconditionally clear the flag.
5572 */
5573 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005574 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005575
5576 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005577 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5578 u8 scan = SCAN_PAGE;
5579 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5580 sizeof(scan), &scan);
5581 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005582 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005583 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005584 hci_req_run(&req, NULL);
5585
5586 hdev->discov_timeout = 0;
5587
Johan Hedberg9a43e252013-10-20 19:00:07 +03005588 new_settings(hdev, NULL);
5589
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005590 hci_dev_unlock(hdev);
5591}
5592
Marcel Holtmann86a75642013-10-15 06:33:54 -07005593void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005594{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005595 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005596
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005597 /* Nothing needed here if there's a pending command since that
5598 * commands request completion callback takes care of everything
5599 * necessary.
5600 */
5601 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005602 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005603
Johan Hedbergbd107992014-02-24 14:52:19 +02005604 /* Powering off may clear the scan mode - don't let that interfere */
5605 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5606 return;
5607
Johan Hedberg9a43e252013-10-20 19:00:07 +03005608 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005609 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005610 } else {
5611 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005612 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005613 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005614
Johan Hedberg9a43e252013-10-20 19:00:07 +03005615 if (changed) {
5616 struct hci_request req;
5617
5618 /* In case this change in discoverable was triggered by
5619 * a disabling of connectable there could be a need to
5620 * update the advertising flags.
5621 */
5622 hci_req_init(&req, hdev);
5623 update_adv_data(&req);
5624 hci_req_run(&req, NULL);
5625
Marcel Holtmann86a75642013-10-15 06:33:54 -07005626 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005627 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005628}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005629
Marcel Holtmanna3309162013-10-15 06:33:55 -07005630void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005631{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005632 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005633
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005634 /* Nothing needed here if there's a pending command since that
5635 * commands request completion callback takes care of everything
5636 * necessary.
5637 */
5638 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005639 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005640
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005641 /* Powering off may clear the scan mode - don't let that interfere */
5642 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5643 return;
5644
Marcel Holtmanna3309162013-10-15 06:33:55 -07005645 if (connectable)
5646 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5647 else
5648 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005649
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005650 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005651 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005652}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005653
Johan Hedberg778b2352014-02-24 14:52:17 +02005654void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5655{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005656 /* Powering off may stop advertising - don't let that interfere */
5657 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5658 return;
5659
Johan Hedberg778b2352014-02-24 14:52:17 +02005660 if (advertising)
5661 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5662 else
5663 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5664}
5665
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005666void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005667{
Johan Hedbergca69b792011-11-11 18:10:00 +02005668 u8 mgmt_err = mgmt_status(status);
5669
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005670 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005671 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005672 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005673
5674 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005675 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005676 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005677}
5678
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005679void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5680 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005681{
Johan Hedberg86742e12011-11-07 23:13:38 +02005682 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005683
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005684 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005685
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005686 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005687 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005688 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005689 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005690 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005691 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005692
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005693 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005694}
Johan Hedbergf7520542011-01-20 12:34:39 +02005695
Johan Hedbergd7b25452014-05-23 13:19:53 +03005696static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5697{
5698 if (ltk->authenticated)
5699 return MGMT_LTK_AUTHENTICATED;
5700
5701 return MGMT_LTK_UNAUTHENTICATED;
5702}
5703
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005704void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005705{
5706 struct mgmt_ev_new_long_term_key ev;
5707
5708 memset(&ev, 0, sizeof(ev));
5709
Marcel Holtmann5192d302014-02-19 17:11:58 -08005710 /* Devices using resolvable or non-resolvable random addresses
5711 * without providing an indentity resolving key don't require
5712 * to store long term keys. Their addresses will change the
5713 * next time around.
5714 *
5715 * Only when a remote device provides an identity address
5716 * make sure the long term key is stored. If the remote
5717 * identity is known, the long term keys are internally
5718 * mapped to the identity address. So allow static random
5719 * and public addresses here.
5720 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005721 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5722 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5723 ev.store_hint = 0x00;
5724 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005725 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005726
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005727 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005728 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005729 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005730 ev.key.enc_size = key->enc_size;
5731 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005732 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005733
Johan Hedberg2ceba532014-06-16 19:25:16 +03005734 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005735 ev.key.master = 1;
5736
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005737 memcpy(ev.key.val, key->val, sizeof(key->val));
5738
Marcel Holtmann083368f2013-10-15 14:26:29 -07005739 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005740}
5741
Johan Hedberg95fbac82014-02-19 15:18:31 +02005742void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5743{
5744 struct mgmt_ev_new_irk ev;
5745
5746 memset(&ev, 0, sizeof(ev));
5747
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005748 /* For identity resolving keys from devices that are already
5749 * using a public address or static random address, do not
5750 * ask for storing this key. The identity resolving key really
5751 * is only mandatory for devices using resovlable random
5752 * addresses.
5753 *
5754 * Storing all identity resolving keys has the downside that
5755 * they will be also loaded on next boot of they system. More
5756 * identity resolving keys, means more time during scanning is
5757 * needed to actually resolve these addresses.
5758 */
5759 if (bacmp(&irk->rpa, BDADDR_ANY))
5760 ev.store_hint = 0x01;
5761 else
5762 ev.store_hint = 0x00;
5763
Johan Hedberg95fbac82014-02-19 15:18:31 +02005764 bacpy(&ev.rpa, &irk->rpa);
5765 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5766 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5767 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5768
5769 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5770}
5771
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005772void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5773 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005774{
5775 struct mgmt_ev_new_csrk ev;
5776
5777 memset(&ev, 0, sizeof(ev));
5778
5779 /* Devices using resolvable or non-resolvable random addresses
5780 * without providing an indentity resolving key don't require
5781 * to store signature resolving keys. Their addresses will change
5782 * the next time around.
5783 *
5784 * Only when a remote device provides an identity address
5785 * make sure the signature resolving key is stored. So allow
5786 * static random and public addresses here.
5787 */
5788 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5789 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5790 ev.store_hint = 0x00;
5791 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005792 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005793
5794 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5795 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5796 ev.key.master = csrk->master;
5797 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5798
5799 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5800}
5801
Andre Guedesffb5a8272014-07-01 18:10:11 -03005802void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005803 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5804 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005805{
5806 struct mgmt_ev_new_conn_param ev;
5807
Johan Hedbergc103aea2014-07-02 17:37:34 +03005808 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5809 return;
5810
Andre Guedesffb5a8272014-07-01 18:10:11 -03005811 memset(&ev, 0, sizeof(ev));
5812 bacpy(&ev.addr.bdaddr, bdaddr);
5813 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005814 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005815 ev.min_interval = cpu_to_le16(min_interval);
5816 ev.max_interval = cpu_to_le16(max_interval);
5817 ev.latency = cpu_to_le16(latency);
5818 ev.timeout = cpu_to_le16(timeout);
5819
5820 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5821}
5822
Marcel Holtmann94933992013-10-15 10:26:39 -07005823static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5824 u8 data_len)
5825{
5826 eir[eir_len++] = sizeof(type) + data_len;
5827 eir[eir_len++] = type;
5828 memcpy(&eir[eir_len], data, data_len);
5829 eir_len += data_len;
5830
5831 return eir_len;
5832}
5833
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005834void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5835 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5836 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005837{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005838 char buf[512];
5839 struct mgmt_ev_device_connected *ev = (void *) buf;
5840 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005841
Johan Hedbergb644ba32012-01-17 21:48:47 +02005842 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005843 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005844
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005845 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005846
Johan Hedbergb644ba32012-01-17 21:48:47 +02005847 if (name_len > 0)
5848 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005849 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005850
5851 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005852 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005853 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005854
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005855 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005856
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005857 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5858 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005859}
5860
Johan Hedberg8962ee72011-01-20 12:40:27 +02005861static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5862{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005863 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005864 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005865 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005866
Johan Hedberg88c3df12012-02-09 14:27:38 +02005867 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5868 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005869
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005870 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005871 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005872
5873 *sk = cmd->sk;
5874 sock_hold(*sk);
5875
Johan Hedberga664b5b2011-02-19 12:06:02 -03005876 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005877}
5878
Johan Hedberg124f6e32012-02-09 13:50:12 +02005879static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005880{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005881 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005882 struct mgmt_cp_unpair_device *cp = cmd->param;
5883 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005884
5885 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005886 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5887 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005888
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005889 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5890
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005891 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005892
5893 mgmt_pending_remove(cmd);
5894}
5895
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005896void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005897 u8 link_type, u8 addr_type, u8 reason,
5898 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005899{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005900 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005901 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005902 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005903
Johan Hedberg8b064a32014-02-24 14:52:22 +02005904 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5905 if (power_off) {
5906 struct mgmt_mode *cp = power_off->param;
5907
5908 /* The connection is still in hci_conn_hash so test for 1
5909 * instead of 0 to know if this is the last one.
5910 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005911 if (!cp->val && hci_conn_count(hdev) == 1) {
5912 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005913 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005914 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005915 }
5916
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005917 if (!mgmt_connected)
5918 return;
5919
Andre Guedes57eb7762013-10-30 19:01:41 -03005920 if (link_type != ACL_LINK && link_type != LE_LINK)
5921 return;
5922
Johan Hedberg744cf192011-11-08 20:40:14 +02005923 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005924
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005925 bacpy(&ev.addr.bdaddr, bdaddr);
5926 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5927 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005928
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005929 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005930
5931 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005932 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005933
Johan Hedberg124f6e32012-02-09 13:50:12 +02005934 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005935 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005936}
5937
Marcel Holtmann78929242013-10-06 23:55:47 -07005938void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5939 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005940{
Andre Guedes3655bba2013-10-30 19:01:40 -03005941 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5942 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005943 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005944 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005945
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005946 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5947 hdev);
5948
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005949 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005950 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005951 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005952
Andre Guedes3655bba2013-10-30 19:01:40 -03005953 cp = cmd->param;
5954
5955 if (bacmp(bdaddr, &cp->addr.bdaddr))
5956 return;
5957
5958 if (cp->addr.type != bdaddr_type)
5959 return;
5960
Johan Hedberg88c3df12012-02-09 14:27:38 +02005961 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005962 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005963
Marcel Holtmann78929242013-10-06 23:55:47 -07005964 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5965 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005966
Johan Hedberga664b5b2011-02-19 12:06:02 -03005967 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005968}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005969
Marcel Holtmann445608d2013-10-06 23:55:48 -07005970void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5971 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005972{
5973 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005974 struct pending_cmd *power_off;
5975
5976 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5977 if (power_off) {
5978 struct mgmt_mode *cp = power_off->param;
5979
5980 /* The connection is still in hci_conn_hash so test for 1
5981 * instead of 0 to know if this is the last one.
5982 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005983 if (!cp->val && hci_conn_count(hdev) == 1) {
5984 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005985 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005986 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005987 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005988
Johan Hedberg4c659c32011-11-07 23:13:39 +02005989 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005990 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005991 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005992
Marcel Holtmann445608d2013-10-06 23:55:48 -07005993 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005994}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005995
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005996void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005997{
5998 struct mgmt_ev_pin_code_request ev;
5999
Johan Hedbergd8457692012-02-17 14:24:57 +02006000 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006001 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006002 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006003
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006004 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006005}
6006
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006007void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6008 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006009{
6010 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006011 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006012
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006013 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006014 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006015 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006016
Johan Hedbergd8457692012-02-17 14:24:57 +02006017 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006018 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006019
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006020 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6021 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006022
Johan Hedberga664b5b2011-02-19 12:06:02 -03006023 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006024}
6025
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006026void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6027 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006028{
6029 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006030 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006031
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006032 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006033 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006034 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006035
Johan Hedbergd8457692012-02-17 14:24:57 +02006036 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006037 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006038
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006039 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6040 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006041
Johan Hedberga664b5b2011-02-19 12:06:02 -03006042 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006043}
Johan Hedberga5c29682011-02-19 12:05:57 -03006044
Johan Hedberg744cf192011-11-08 20:40:14 +02006045int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006046 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006047 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006048{
6049 struct mgmt_ev_user_confirm_request ev;
6050
Johan Hedberg744cf192011-11-08 20:40:14 +02006051 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006052
Johan Hedberg272d90d2012-02-09 15:26:12 +02006053 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006054 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006055 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006056 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006057
Johan Hedberg744cf192011-11-08 20:40:14 +02006058 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006059 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006060}
6061
Johan Hedberg272d90d2012-02-09 15:26:12 +02006062int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006063 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006064{
6065 struct mgmt_ev_user_passkey_request ev;
6066
6067 BT_DBG("%s", hdev->name);
6068
Johan Hedberg272d90d2012-02-09 15:26:12 +02006069 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006070 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006071
6072 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006073 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006074}
6075
Brian Gix0df4c182011-11-16 13:53:13 -08006076static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006077 u8 link_type, u8 addr_type, u8 status,
6078 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006079{
6080 struct pending_cmd *cmd;
6081 struct mgmt_rp_user_confirm_reply rp;
6082 int err;
6083
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006084 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006085 if (!cmd)
6086 return -ENOENT;
6087
Johan Hedberg272d90d2012-02-09 15:26:12 +02006088 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006089 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006090 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006091 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006092
Johan Hedberga664b5b2011-02-19 12:06:02 -03006093 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006094
6095 return err;
6096}
6097
Johan Hedberg744cf192011-11-08 20:40:14 +02006098int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006099 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006100{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006101 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006102 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006103}
6104
Johan Hedberg272d90d2012-02-09 15:26:12 +02006105int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006106 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006107{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006108 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006109 status,
6110 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006111}
Johan Hedberg2a611692011-02-19 12:06:00 -03006112
Brian Gix604086b2011-11-23 08:28:33 -08006113int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006114 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006115{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006116 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006117 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006118}
6119
Johan Hedberg272d90d2012-02-09 15:26:12 +02006120int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006121 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006122{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006123 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006124 status,
6125 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006126}
6127
Johan Hedberg92a25252012-09-06 18:39:26 +03006128int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6129 u8 link_type, u8 addr_type, u32 passkey,
6130 u8 entered)
6131{
6132 struct mgmt_ev_passkey_notify ev;
6133
6134 BT_DBG("%s", hdev->name);
6135
6136 bacpy(&ev.addr.bdaddr, bdaddr);
6137 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6138 ev.passkey = __cpu_to_le32(passkey);
6139 ev.entered = entered;
6140
6141 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6142}
6143
Marcel Holtmanne5460992013-10-15 14:26:23 -07006144void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6145 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006146{
6147 struct mgmt_ev_auth_failed ev;
6148
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006149 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006150 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006151 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006152
Marcel Holtmanne5460992013-10-15 14:26:23 -07006153 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006154}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006155
Marcel Holtmann464996a2013-10-15 14:26:24 -07006156void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006157{
6158 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006159 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006160
6161 if (status) {
6162 u8 mgmt_err = mgmt_status(status);
6163 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006164 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006165 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006166 }
6167
Marcel Holtmann464996a2013-10-15 14:26:24 -07006168 if (test_bit(HCI_AUTH, &hdev->flags))
6169 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6170 &hdev->dev_flags);
6171 else
6172 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6173 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006174
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006175 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006176 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006177
Johan Hedberg47990ea2012-02-22 11:58:37 +02006178 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006179 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006180
6181 if (match.sk)
6182 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006183}
6184
Johan Hedberg890ea892013-03-15 17:06:52 -05006185static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006186{
Johan Hedberg890ea892013-03-15 17:06:52 -05006187 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006188 struct hci_cp_write_eir cp;
6189
Johan Hedberg976eb202012-10-24 21:12:01 +03006190 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006191 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006192
Johan Hedbergc80da272012-02-22 15:38:48 +02006193 memset(hdev->eir, 0, sizeof(hdev->eir));
6194
Johan Hedbergcacaf522012-02-21 00:52:42 +02006195 memset(&cp, 0, sizeof(cp));
6196
Johan Hedberg890ea892013-03-15 17:06:52 -05006197 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006198}
6199
Marcel Holtmann3e248562013-10-15 14:26:25 -07006200void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006201{
6202 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006203 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006204 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006205
6206 if (status) {
6207 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006208
6209 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006210 &hdev->dev_flags)) {
6211 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006212 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006213 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006214
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006215 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6216 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006217 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006218 }
6219
6220 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006221 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006222 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006223 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6224 if (!changed)
6225 changed = test_and_clear_bit(HCI_HS_ENABLED,
6226 &hdev->dev_flags);
6227 else
6228 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006229 }
6230
6231 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6232
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006233 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006234 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006235
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006236 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006237 sock_put(match.sk);
6238
Johan Hedberg890ea892013-03-15 17:06:52 -05006239 hci_req_init(&req, hdev);
6240
Johan Hedberg37699722014-06-24 14:00:27 +03006241 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6242 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6243 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6244 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006245 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006246 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006247 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006248 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006249
6250 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006251}
6252
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006253void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6254{
6255 struct cmd_lookup match = { NULL, hdev };
6256 bool changed = false;
6257
6258 if (status) {
6259 u8 mgmt_err = mgmt_status(status);
6260
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006261 if (enable) {
6262 if (test_and_clear_bit(HCI_SC_ENABLED,
6263 &hdev->dev_flags))
6264 new_settings(hdev, NULL);
6265 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6266 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006267
6268 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6269 cmd_status_rsp, &mgmt_err);
6270 return;
6271 }
6272
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006273 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006274 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006275 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006276 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006277 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6278 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006279
6280 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6281 settings_rsp, &match);
6282
6283 if (changed)
6284 new_settings(hdev, match.sk);
6285
6286 if (match.sk)
6287 sock_put(match.sk);
6288}
6289
Johan Hedberg92da6092013-03-15 17:06:55 -05006290static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006291{
6292 struct cmd_lookup *match = data;
6293
Johan Hedberg90e70452012-02-23 23:09:40 +02006294 if (match->sk == NULL) {
6295 match->sk = cmd->sk;
6296 sock_hold(match->sk);
6297 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006298}
6299
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006300void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6301 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006302{
Johan Hedberg90e70452012-02-23 23:09:40 +02006303 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006304
Johan Hedberg92da6092013-03-15 17:06:55 -05006305 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6306 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6307 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006308
6309 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006310 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6311 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006312
6313 if (match.sk)
6314 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006315}
6316
Marcel Holtmann7667da32013-10-15 14:26:27 -07006317void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006318{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006319 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006320 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006321
Johan Hedberg13928972013-03-15 17:07:00 -05006322 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006323 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006324
6325 memset(&ev, 0, sizeof(ev));
6326 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006327 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006328
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006329 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006330 if (!cmd) {
6331 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006332
Johan Hedberg13928972013-03-15 17:07:00 -05006333 /* If this is a HCI command related to powering on the
6334 * HCI dev don't send any mgmt signals.
6335 */
6336 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006337 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006338 }
6339
Marcel Holtmann7667da32013-10-15 14:26:27 -07006340 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6341 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006342}
Szymon Jancc35938b2011-03-22 13:12:21 +01006343
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006344void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6345 u8 *randomizer192, u8 *hash256,
6346 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006347{
6348 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006349
Johan Hedberg744cf192011-11-08 20:40:14 +02006350 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006351
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006352 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006353 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006354 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006355
6356 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006357 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6358 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006359 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006360 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6361 hash256 && randomizer256) {
6362 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006363
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006364 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6365 memcpy(rp.randomizer192, randomizer192,
6366 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006367
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006368 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6369 memcpy(rp.randomizer256, randomizer256,
6370 sizeof(rp.randomizer256));
6371
6372 cmd_complete(cmd->sk, hdev->id,
6373 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6374 &rp, sizeof(rp));
6375 } else {
6376 struct mgmt_rp_read_local_oob_data rp;
6377
6378 memcpy(rp.hash, hash192, sizeof(rp.hash));
6379 memcpy(rp.randomizer, randomizer192,
6380 sizeof(rp.randomizer));
6381
6382 cmd_complete(cmd->sk, hdev->id,
6383 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6384 &rp, sizeof(rp));
6385 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006386 }
6387
6388 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006389}
Johan Hedberge17acd42011-03-30 23:57:16 +03006390
Marcel Holtmann901801b2013-10-06 23:55:51 -07006391void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006392 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6393 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006394{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006395 char buf[512];
6396 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006397 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006398 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006399
Andre Guedes12602d02013-04-30 15:29:40 -03006400 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006401 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006402
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006403 /* Make sure that the buffer is big enough. The 5 extra bytes
6404 * are for the potential CoD field.
6405 */
6406 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006407 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006408
Johan Hedberg1dc06092012-01-15 21:01:23 +02006409 memset(buf, 0, sizeof(buf));
6410
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006411 irk = hci_get_irk(hdev, bdaddr, addr_type);
6412 if (irk) {
6413 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6414 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6415 } else {
6416 bacpy(&ev->addr.bdaddr, bdaddr);
6417 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6418 }
6419
Johan Hedberge319d2e2012-01-15 19:51:59 +02006420 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006421 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006422
Johan Hedberg1dc06092012-01-15 21:01:23 +02006423 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006424 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006425
Johan Hedberg1dc06092012-01-15 21:01:23 +02006426 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6427 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006428 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006429
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006430 if (scan_rsp_len > 0)
6431 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6432
6433 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6434 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006435
Marcel Holtmann901801b2013-10-06 23:55:51 -07006436 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006437}
Johan Hedberga88a9652011-03-30 13:18:12 +03006438
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006439void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6440 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006441{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006442 struct mgmt_ev_device_found *ev;
6443 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6444 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006445
Johan Hedbergb644ba32012-01-17 21:48:47 +02006446 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006447
Johan Hedbergb644ba32012-01-17 21:48:47 +02006448 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006449
Johan Hedbergb644ba32012-01-17 21:48:47 +02006450 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006451 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006452 ev->rssi = rssi;
6453
6454 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006455 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006456
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006457 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006458
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006459 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006460}
Johan Hedberg314b2382011-04-27 10:29:57 -04006461
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006462void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006463{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006464 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006465 struct pending_cmd *cmd;
6466
Andre Guedes343fb142011-11-22 17:14:19 -03006467 BT_DBG("%s discovering %u", hdev->name, discovering);
6468
Johan Hedberg164a6e72011-11-01 17:06:44 +02006469 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006470 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006471 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006472 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006473
6474 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006475 u8 type = hdev->discovery.type;
6476
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006477 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6478 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006479 mgmt_pending_remove(cmd);
6480 }
6481
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006482 memset(&ev, 0, sizeof(ev));
6483 ev.type = hdev->discovery.type;
6484 ev.discovering = discovering;
6485
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006486 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006487}
Antti Julku5e762442011-08-25 16:48:02 +03006488
Marcel Holtmann5976e602013-10-06 04:08:14 -07006489static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6490{
6491 BT_DBG("%s status %u", hdev->name, status);
6492
6493 /* Clear the advertising mgmt setting if we failed to re-enable it */
6494 if (status) {
6495 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006496 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006497 }
6498}
6499
6500void mgmt_reenable_advertising(struct hci_dev *hdev)
6501{
6502 struct hci_request req;
6503
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006504 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006505 return;
6506
6507 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6508 return;
6509
6510 hci_req_init(&req, hdev);
6511 enable_advertising(&req);
6512
6513 /* If this fails we have no option but to let user space know
6514 * that we've disabled advertising.
6515 */
6516 if (hci_req_run(&req, adv_enable_complete) < 0) {
6517 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006518 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006519 }
6520}