blob: 6faa4616cbfed57f2a110fdfafc98aa3e839327d [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020089};
90
91static const u16 mgmt_events[] = {
92 MGMT_EV_CONTROLLER_ERROR,
93 MGMT_EV_INDEX_ADDED,
94 MGMT_EV_INDEX_REMOVED,
95 MGMT_EV_NEW_SETTINGS,
96 MGMT_EV_CLASS_OF_DEV_CHANGED,
97 MGMT_EV_LOCAL_NAME_CHANGED,
98 MGMT_EV_NEW_LINK_KEY,
99 MGMT_EV_NEW_LONG_TERM_KEY,
100 MGMT_EV_DEVICE_CONNECTED,
101 MGMT_EV_DEVICE_DISCONNECTED,
102 MGMT_EV_CONNECT_FAILED,
103 MGMT_EV_PIN_CODE_REQUEST,
104 MGMT_EV_USER_CONFIRM_REQUEST,
105 MGMT_EV_USER_PASSKEY_REQUEST,
106 MGMT_EV_AUTH_FAILED,
107 MGMT_EV_DEVICE_FOUND,
108 MGMT_EV_DISCOVERING,
109 MGMT_EV_DEVICE_BLOCKED,
110 MGMT_EV_DEVICE_UNBLOCKED,
111 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300112 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800113 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700114 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200115};
116
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800117#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200118
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200119#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
120 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
121
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200122struct pending_cmd {
123 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200124 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200125 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100126 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200127 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300128 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200129};
130
Johan Hedbergca69b792011-11-11 18:10:00 +0200131/* HCI to MGMT error code conversion table */
132static u8 mgmt_status_table[] = {
133 MGMT_STATUS_SUCCESS,
134 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
135 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
136 MGMT_STATUS_FAILED, /* Hardware Failure */
137 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
138 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200139 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200140 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
141 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
142 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
143 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
144 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
145 MGMT_STATUS_BUSY, /* Command Disallowed */
146 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
147 MGMT_STATUS_REJECTED, /* Rejected Security */
148 MGMT_STATUS_REJECTED, /* Rejected Personal */
149 MGMT_STATUS_TIMEOUT, /* Host Timeout */
150 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
151 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
152 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
153 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
154 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
155 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
156 MGMT_STATUS_BUSY, /* Repeated Attempts */
157 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
158 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
159 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
160 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
161 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
162 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
163 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
164 MGMT_STATUS_FAILED, /* Unspecified Error */
165 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
166 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
167 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
168 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
169 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
170 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
171 MGMT_STATUS_FAILED, /* Unit Link Key Used */
172 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
173 MGMT_STATUS_TIMEOUT, /* Instant Passed */
174 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
175 MGMT_STATUS_FAILED, /* Transaction Collision */
176 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
177 MGMT_STATUS_REJECTED, /* QoS Rejected */
178 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
179 MGMT_STATUS_REJECTED, /* Insufficient Security */
180 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
181 MGMT_STATUS_BUSY, /* Role Switch Pending */
182 MGMT_STATUS_FAILED, /* Slot Violation */
183 MGMT_STATUS_FAILED, /* Role Switch Failed */
184 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
185 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
186 MGMT_STATUS_BUSY, /* Host Busy Pairing */
187 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
188 MGMT_STATUS_BUSY, /* Controller Busy */
189 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
190 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
191 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
192 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
193 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
194};
195
196static u8 mgmt_status(u8 hci_status)
197{
198 if (hci_status < ARRAY_SIZE(mgmt_status_table))
199 return mgmt_status_table[hci_status];
200
201 return MGMT_STATUS_FAILED;
202}
203
Szymon Janc4e51eae2011-02-25 19:05:48 +0100204static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200205{
206 struct sk_buff *skb;
207 struct mgmt_hdr *hdr;
208 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300209 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200210
Szymon Janc34eb5252011-02-28 14:10:08 +0100211 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200212
Andre Guedes790eff42012-06-07 19:05:46 -0300213 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200214 if (!skb)
215 return -ENOMEM;
216
217 hdr = (void *) skb_put(skb, sizeof(*hdr));
218
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700219 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100220 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200221 hdr->len = cpu_to_le16(sizeof(*ev));
222
223 ev = (void *) skb_put(skb, sizeof(*ev));
224 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200225 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200226
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300227 err = sock_queue_rcv_skb(sk, skb);
228 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200229 kfree_skb(skb);
230
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300231 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200232}
233
Johan Hedbergaee9b212012-02-18 15:07:59 +0200234static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300235 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200236{
237 struct sk_buff *skb;
238 struct mgmt_hdr *hdr;
239 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300240 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200241
242 BT_DBG("sock %p", sk);
243
Andre Guedes790eff42012-06-07 19:05:46 -0300244 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200245 if (!skb)
246 return -ENOMEM;
247
248 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200249
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700250 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100251 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200252 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200253
Johan Hedberga38528f2011-01-22 06:46:43 +0200254 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200255 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200256 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100257
258 if (rp)
259 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200260
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300261 err = sock_queue_rcv_skb(sk, skb);
262 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200263 kfree_skb(skb);
264
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100265 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200266}
267
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300268static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
269 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200270{
271 struct mgmt_rp_read_version rp;
272
273 BT_DBG("sock %p", sk);
274
275 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700276 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200277
Johan Hedbergaee9b212012-02-18 15:07:59 +0200278 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300279 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200280}
281
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300282static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
283 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200284{
285 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200286 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
287 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200288 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200289 size_t rp_size;
290 int i, err;
291
292 BT_DBG("sock %p", sk);
293
294 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
295
296 rp = kmalloc(rp_size, GFP_KERNEL);
297 if (!rp)
298 return -ENOMEM;
299
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700300 rp->num_commands = cpu_to_le16(num_commands);
301 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200302
303 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
304 put_unaligned_le16(mgmt_commands[i], opcode);
305
306 for (i = 0; i < num_events; i++, opcode++)
307 put_unaligned_le16(mgmt_events[i], opcode);
308
Johan Hedbergaee9b212012-02-18 15:07:59 +0200309 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300310 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311 kfree(rp);
312
313 return err;
314}
315
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300316static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
317 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200319 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200320 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200321 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200322 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300323 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200324
325 BT_DBG("sock %p", sk);
326
327 read_lock(&hci_dev_list_lock);
328
329 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300330 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700331 if (d->dev_type == HCI_BREDR)
332 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200333 }
334
Johan Hedberga38528f2011-01-22 06:46:43 +0200335 rp_len = sizeof(*rp) + (2 * count);
336 rp = kmalloc(rp_len, GFP_ATOMIC);
337 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100338 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100340 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200341
Johan Hedberg476e44c2012-10-19 20:10:46 +0300342 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200343 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200344 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200345 continue;
346
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700347 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
348 continue;
349
Marcel Holtmann1514b892013-10-06 08:25:01 -0700350 if (d->dev_type == HCI_BREDR) {
351 rp->index[count++] = cpu_to_le16(d->id);
352 BT_DBG("Added hci%u", d->id);
353 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200354 }
355
Johan Hedberg476e44c2012-10-19 20:10:46 +0300356 rp->num_controllers = cpu_to_le16(count);
357 rp_len = sizeof(*rp) + (2 * count);
358
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200359 read_unlock(&hci_dev_list_lock);
360
Johan Hedbergaee9b212012-02-18 15:07:59 +0200361 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300362 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 kfree(rp);
365
366 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367}
368
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200369static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200370{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200371 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200372
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200373 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200374 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800375 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200376
Andre Guedesed3fa312012-07-24 15:03:46 -0300377 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300378 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500379 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
380 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300381 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200382 settings |= MGMT_SETTING_BREDR;
383 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700384
385 if (lmp_ssp_capable(hdev)) {
386 settings |= MGMT_SETTING_SSP;
387 settings |= MGMT_SETTING_HS;
388 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800389
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800390 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200391 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800392 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700393 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100394
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300395 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200396 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300397 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200398 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300399 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200400
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200401 return settings;
402}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200403
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200404static u32 get_current_settings(struct hci_dev *hdev)
405{
406 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200407
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200408 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100409 settings |= MGMT_SETTING_POWERED;
410
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200411 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200412 settings |= MGMT_SETTING_CONNECTABLE;
413
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500414 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
415 settings |= MGMT_SETTING_FAST_CONNECTABLE;
416
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200417 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200418 settings |= MGMT_SETTING_DISCOVERABLE;
419
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200420 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200421 settings |= MGMT_SETTING_PAIRABLE;
422
Johan Hedberg56f87902013-10-02 13:43:13 +0300423 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200424 settings |= MGMT_SETTING_BREDR;
425
Johan Hedberg06199cf2012-02-22 16:37:11 +0200426 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200427 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200428
Johan Hedberg47990ea2012-02-22 11:58:37 +0200429 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200430 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200431
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200432 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200433 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200434
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200435 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
436 settings |= MGMT_SETTING_HS;
437
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200438 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300439 settings |= MGMT_SETTING_ADVERTISING;
440
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800441 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
442 settings |= MGMT_SETTING_SECURE_CONN;
443
Johan Hedberg0663b292014-06-24 13:15:50 +0300444 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800445 settings |= MGMT_SETTING_DEBUG_KEYS;
446
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200447 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
448 settings |= MGMT_SETTING_PRIVACY;
449
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200450 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200451}
452
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300453#define PNP_INFO_SVCLASS_ID 0x1200
454
Johan Hedberg213202e2013-01-27 00:31:33 +0200455static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
456{
457 u8 *ptr = data, *uuids_start = NULL;
458 struct bt_uuid *uuid;
459
460 if (len < 4)
461 return ptr;
462
463 list_for_each_entry(uuid, &hdev->uuids, list) {
464 u16 uuid16;
465
466 if (uuid->size != 16)
467 continue;
468
469 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
470 if (uuid16 < 0x1100)
471 continue;
472
473 if (uuid16 == PNP_INFO_SVCLASS_ID)
474 continue;
475
476 if (!uuids_start) {
477 uuids_start = ptr;
478 uuids_start[0] = 1;
479 uuids_start[1] = EIR_UUID16_ALL;
480 ptr += 2;
481 }
482
483 /* Stop if not enough space to put next UUID */
484 if ((ptr - data) + sizeof(u16) > len) {
485 uuids_start[1] = EIR_UUID16_SOME;
486 break;
487 }
488
489 *ptr++ = (uuid16 & 0x00ff);
490 *ptr++ = (uuid16 & 0xff00) >> 8;
491 uuids_start[0] += sizeof(uuid16);
492 }
493
494 return ptr;
495}
496
Johan Hedbergcdf19632013-01-27 00:31:34 +0200497static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
498{
499 u8 *ptr = data, *uuids_start = NULL;
500 struct bt_uuid *uuid;
501
502 if (len < 6)
503 return ptr;
504
505 list_for_each_entry(uuid, &hdev->uuids, list) {
506 if (uuid->size != 32)
507 continue;
508
509 if (!uuids_start) {
510 uuids_start = ptr;
511 uuids_start[0] = 1;
512 uuids_start[1] = EIR_UUID32_ALL;
513 ptr += 2;
514 }
515
516 /* Stop if not enough space to put next UUID */
517 if ((ptr - data) + sizeof(u32) > len) {
518 uuids_start[1] = EIR_UUID32_SOME;
519 break;
520 }
521
522 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
523 ptr += sizeof(u32);
524 uuids_start[0] += sizeof(u32);
525 }
526
527 return ptr;
528}
529
Johan Hedbergc00d5752013-01-27 00:31:35 +0200530static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
531{
532 u8 *ptr = data, *uuids_start = NULL;
533 struct bt_uuid *uuid;
534
535 if (len < 18)
536 return ptr;
537
538 list_for_each_entry(uuid, &hdev->uuids, list) {
539 if (uuid->size != 128)
540 continue;
541
542 if (!uuids_start) {
543 uuids_start = ptr;
544 uuids_start[0] = 1;
545 uuids_start[1] = EIR_UUID128_ALL;
546 ptr += 2;
547 }
548
549 /* Stop if not enough space to put next UUID */
550 if ((ptr - data) + 16 > len) {
551 uuids_start[1] = EIR_UUID128_SOME;
552 break;
553 }
554
555 memcpy(ptr, uuid->uuid, 16);
556 ptr += 16;
557 uuids_start[0] += 16;
558 }
559
560 return ptr;
561}
562
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300563static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
564{
565 struct pending_cmd *cmd;
566
567 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
568 if (cmd->opcode == opcode)
569 return cmd;
570 }
571
572 return NULL;
573}
574
Johan Hedberg95868422014-06-28 17:54:07 +0300575static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
576 struct hci_dev *hdev,
577 const void *data)
578{
579 struct pending_cmd *cmd;
580
581 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
582 if (cmd->user_data != data)
583 continue;
584 if (cmd->opcode == opcode)
585 return cmd;
586 }
587
588 return NULL;
589}
590
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700591static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
592{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700593 u8 ad_len = 0;
594 size_t name_len;
595
596 name_len = strlen(hdev->dev_name);
597 if (name_len > 0) {
598 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
599
600 if (name_len > max_len) {
601 name_len = max_len;
602 ptr[1] = EIR_NAME_SHORT;
603 } else
604 ptr[1] = EIR_NAME_COMPLETE;
605
606 ptr[0] = name_len + 1;
607
608 memcpy(ptr + 2, hdev->dev_name, name_len);
609
610 ad_len += (name_len + 2);
611 ptr += (name_len + 2);
612 }
613
614 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615}
616
617static void update_scan_rsp_data(struct hci_request *req)
618{
619 struct hci_dev *hdev = req->hdev;
620 struct hci_cp_le_set_scan_rsp_data cp;
621 u8 len;
622
Johan Hedberg7751ef12013-10-19 23:38:15 +0300623 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700624 return;
625
626 memset(&cp, 0, sizeof(cp));
627
628 len = create_scan_rsp_data(hdev, cp.data);
629
Johan Hedbergeb438b52013-10-16 15:31:07 +0300630 if (hdev->scan_rsp_data_len == len &&
631 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700632 return;
633
Johan Hedbergeb438b52013-10-16 15:31:07 +0300634 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
635 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700636
637 cp.length = len;
638
639 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
640}
641
Johan Hedberg9a43e252013-10-20 19:00:07 +0300642static u8 get_adv_discov_flags(struct hci_dev *hdev)
643{
644 struct pending_cmd *cmd;
645
646 /* If there's a pending mgmt command the flags will not yet have
647 * their final values, so check for this first.
648 */
649 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
650 if (cmd) {
651 struct mgmt_mode *cp = cmd->param;
652 if (cp->val == 0x01)
653 return LE_AD_GENERAL;
654 else if (cp->val == 0x02)
655 return LE_AD_LIMITED;
656 } else {
657 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
658 return LE_AD_LIMITED;
659 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
660 return LE_AD_GENERAL;
661 }
662
663 return 0;
664}
665
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700666static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700667{
668 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700669
Johan Hedberg9a43e252013-10-20 19:00:07 +0300670 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700671
Johan Hedberge8340042014-01-30 11:16:50 -0800672 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700673 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700674
675 if (flags) {
676 BT_DBG("adv flags 0x%02x", flags);
677
678 ptr[0] = 2;
679 ptr[1] = EIR_FLAGS;
680 ptr[2] = flags;
681
682 ad_len += 3;
683 ptr += 3;
684 }
685
686 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
687 ptr[0] = 2;
688 ptr[1] = EIR_TX_POWER;
689 ptr[2] = (u8) hdev->adv_tx_power;
690
691 ad_len += 3;
692 ptr += 3;
693 }
694
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700695 return ad_len;
696}
697
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700698static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700699{
700 struct hci_dev *hdev = req->hdev;
701 struct hci_cp_le_set_adv_data cp;
702 u8 len;
703
Johan Hedberg10994ce2013-10-19 23:38:16 +0300704 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700705 return;
706
707 memset(&cp, 0, sizeof(cp));
708
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700709 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700710
711 if (hdev->adv_data_len == len &&
712 memcmp(cp.data, hdev->adv_data, len) == 0)
713 return;
714
715 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
716 hdev->adv_data_len = len;
717
718 cp.length = len;
719
720 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
721}
722
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300723static void create_eir(struct hci_dev *hdev, u8 *data)
724{
725 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726 size_t name_len;
727
728 name_len = strlen(hdev->dev_name);
729
730 if (name_len > 0) {
731 /* EIR Data type */
732 if (name_len > 48) {
733 name_len = 48;
734 ptr[1] = EIR_NAME_SHORT;
735 } else
736 ptr[1] = EIR_NAME_COMPLETE;
737
738 /* EIR Data length */
739 ptr[0] = name_len + 1;
740
741 memcpy(ptr + 2, hdev->dev_name, name_len);
742
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300743 ptr += (name_len + 2);
744 }
745
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100746 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700747 ptr[0] = 2;
748 ptr[1] = EIR_TX_POWER;
749 ptr[2] = (u8) hdev->inq_tx_power;
750
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700751 ptr += 3;
752 }
753
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700754 if (hdev->devid_source > 0) {
755 ptr[0] = 9;
756 ptr[1] = EIR_DEVICE_ID;
757
758 put_unaligned_le16(hdev->devid_source, ptr + 2);
759 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
760 put_unaligned_le16(hdev->devid_product, ptr + 6);
761 put_unaligned_le16(hdev->devid_version, ptr + 8);
762
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700763 ptr += 10;
764 }
765
Johan Hedberg213202e2013-01-27 00:31:33 +0200766 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200767 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200768 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300769}
770
Johan Hedberg890ea892013-03-15 17:06:52 -0500771static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300772{
Johan Hedberg890ea892013-03-15 17:06:52 -0500773 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300774 struct hci_cp_write_eir cp;
775
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200776 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500777 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200778
Johan Hedberg976eb202012-10-24 21:12:01 +0300779 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200782 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500783 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300784
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200785 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500786 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300787
788 memset(&cp, 0, sizeof(cp));
789
790 create_eir(hdev, cp.data);
791
792 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500793 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300794
795 memcpy(hdev->eir, cp.data, sizeof(cp.data));
796
Johan Hedberg890ea892013-03-15 17:06:52 -0500797 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300798}
799
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200800static u8 get_service_classes(struct hci_dev *hdev)
801{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300802 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200803 u8 val = 0;
804
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300805 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200806 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200807
808 return val;
809}
810
Johan Hedberg890ea892013-03-15 17:06:52 -0500811static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200812{
Johan Hedberg890ea892013-03-15 17:06:52 -0500813 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200814 u8 cod[3];
815
816 BT_DBG("%s", hdev->name);
817
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200818 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500819 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200820
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300821 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
822 return;
823
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200824 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500825 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200826
827 cod[0] = hdev->minor_class;
828 cod[1] = hdev->major_class;
829 cod[2] = get_service_classes(hdev);
830
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700831 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
832 cod[1] |= 0x20;
833
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200834 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500835 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200836
Johan Hedberg890ea892013-03-15 17:06:52 -0500837 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200838}
839
Johan Hedberga4858cb2014-02-25 19:56:31 +0200840static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200841{
842 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200843
844 /* If there's a pending mgmt command the flag will not yet have
845 * it's final value, so check for this first.
846 */
847 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
848 if (cmd) {
849 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200850 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200851 }
852
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200854}
855
856static void enable_advertising(struct hci_request *req)
857{
858 struct hci_dev *hdev = req->hdev;
859 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200860 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200861 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200862
Johan Hedberg8d972502014-02-28 12:54:14 +0200863 /* Clear the HCI_ADVERTISING bit temporarily so that the
864 * hci_update_random_address knows that it's safe to go ahead
865 * and write a new random address. The flag will be set back on
866 * as soon as the SET_ADV_ENABLE HCI command completes.
867 */
868 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
869
Johan Hedberga4858cb2014-02-25 19:56:31 +0200870 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200871
Johan Hedberga4858cb2014-02-25 19:56:31 +0200872 /* Set require_privacy to true only when non-connectable
873 * advertising is used. In that case it is fine to use a
874 * non-resolvable private address.
875 */
876 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200877 return;
878
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800879 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700880 cp.min_interval = cpu_to_le16(0x0800);
881 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200882 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200883 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200884 cp.channel_map = hdev->le_adv_channel_map;
885
886 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
887
888 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
889}
890
891static void disable_advertising(struct hci_request *req)
892{
893 u8 enable = 0x00;
894
895 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
896}
897
Johan Hedberg7d785252011-12-15 00:47:39 +0200898static void service_cache_off(struct work_struct *work)
899{
900 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300901 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500902 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200903
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200904 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200905 return;
906
Johan Hedberg890ea892013-03-15 17:06:52 -0500907 hci_req_init(&req, hdev);
908
Johan Hedberg7d785252011-12-15 00:47:39 +0200909 hci_dev_lock(hdev);
910
Johan Hedberg890ea892013-03-15 17:06:52 -0500911 update_eir(&req);
912 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200913
914 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500915
916 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200917}
918
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200919static void rpa_expired(struct work_struct *work)
920{
921 struct hci_dev *hdev = container_of(work, struct hci_dev,
922 rpa_expired.work);
923 struct hci_request req;
924
925 BT_DBG("");
926
927 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
928
929 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
930 hci_conn_num(hdev, LE_LINK) > 0)
931 return;
932
933 /* The generation of a new RPA and programming it into the
934 * controller happens in the enable_advertising() function.
935 */
936
937 hci_req_init(&req, hdev);
938
939 disable_advertising(&req);
940 enable_advertising(&req);
941
942 hci_req_run(&req, NULL);
943}
944
Johan Hedberg6a919082012-02-28 06:17:26 +0200945static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200946{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200947 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200948 return;
949
Johan Hedberg4f87da82012-03-02 19:55:56 +0200950 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200951 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200952
Johan Hedberg4f87da82012-03-02 19:55:56 +0200953 /* Non-mgmt controlled devices get this bit set
954 * implicitly so that pairing works for them, however
955 * for mgmt we require user-space to explicitly enable
956 * it
957 */
958 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200959}
960
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200961static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300962 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200963{
964 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200965
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200966 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300968 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200969
Johan Hedberg03811012010-12-08 00:21:06 +0200970 memset(&rp, 0, sizeof(rp));
971
Johan Hedberg03811012010-12-08 00:21:06 +0200972 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200973
974 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200975 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200976
977 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
978 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
979
980 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200981
982 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200983 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200984
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300985 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200986
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200987 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300988 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200989}
990
991static void mgmt_pending_free(struct pending_cmd *cmd)
992{
993 sock_put(cmd->sk);
994 kfree(cmd->param);
995 kfree(cmd);
996}
997
998static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300999 struct hci_dev *hdev, void *data,
1000 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001001{
1002 struct pending_cmd *cmd;
1003
Johan Hedbergfca20012014-06-28 17:54:05 +03001004 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001005 if (!cmd)
1006 return NULL;
1007
1008 cmd->opcode = opcode;
1009 cmd->index = hdev->id;
1010
Andre Guedes12b94562012-06-07 19:05:45 -03001011 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001012 if (!cmd->param) {
1013 kfree(cmd);
1014 return NULL;
1015 }
1016
1017 if (data)
1018 memcpy(cmd->param, data, len);
1019
1020 cmd->sk = sk;
1021 sock_hold(sk);
1022
1023 list_add(&cmd->list, &hdev->mgmt_pending);
1024
1025 return cmd;
1026}
1027
1028static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001029 void (*cb)(struct pending_cmd *cmd,
1030 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001031 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001032{
Andre Guedesa3d09352013-02-01 11:21:30 -03001033 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001034
Andre Guedesa3d09352013-02-01 11:21:30 -03001035 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001036 if (opcode > 0 && cmd->opcode != opcode)
1037 continue;
1038
1039 cb(cmd, data);
1040 }
1041}
1042
Johan Hedberg03811012010-12-08 00:21:06 +02001043static void mgmt_pending_remove(struct pending_cmd *cmd)
1044{
1045 list_del(&cmd->list);
1046 mgmt_pending_free(cmd);
1047}
1048
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001049static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001050{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001051 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001052
Johan Hedbergaee9b212012-02-18 15:07:59 +02001053 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001054 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001055}
1056
Johan Hedberg8b064a32014-02-24 14:52:22 +02001057static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1058{
1059 BT_DBG("%s status 0x%02x", hdev->name, status);
1060
Johan Hedberga3172b72014-02-28 09:33:44 +02001061 if (hci_conn_count(hdev) == 0) {
1062 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001063 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001064 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001065}
1066
Johan Hedberg21a60d32014-06-10 14:05:58 +03001067static void hci_stop_discovery(struct hci_request *req)
1068{
1069 struct hci_dev *hdev = req->hdev;
1070 struct hci_cp_remote_name_req_cancel cp;
1071 struct inquiry_entry *e;
1072
1073 switch (hdev->discovery.state) {
1074 case DISCOVERY_FINDING:
1075 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1076 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1077 } else {
1078 cancel_delayed_work(&hdev->le_scan_disable);
1079 hci_req_add_le_scan_disable(req);
1080 }
1081
1082 break;
1083
1084 case DISCOVERY_RESOLVING:
1085 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1086 NAME_PENDING);
1087 if (!e)
1088 return;
1089
1090 bacpy(&cp.bdaddr, &e->data.bdaddr);
1091 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1092 &cp);
1093
1094 break;
1095
1096 default:
1097 /* Passive scanning */
1098 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1099 hci_req_add_le_scan_disable(req);
1100 break;
1101 }
1102}
1103
Johan Hedberg8b064a32014-02-24 14:52:22 +02001104static int clean_up_hci_state(struct hci_dev *hdev)
1105{
1106 struct hci_request req;
1107 struct hci_conn *conn;
1108
1109 hci_req_init(&req, hdev);
1110
1111 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1112 test_bit(HCI_PSCAN, &hdev->flags)) {
1113 u8 scan = 0x00;
1114 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1115 }
1116
1117 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1118 disable_advertising(&req);
1119
Johan Hedbergf8680f12014-06-10 14:05:59 +03001120 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001121
1122 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1123 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001124 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001125
Johan Hedbergc9910d02014-02-27 14:35:12 +02001126 switch (conn->state) {
1127 case BT_CONNECTED:
1128 case BT_CONFIG:
1129 dc.handle = cpu_to_le16(conn->handle);
1130 dc.reason = 0x15; /* Terminated due to Power Off */
1131 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1132 break;
1133 case BT_CONNECT:
1134 if (conn->type == LE_LINK)
1135 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1136 0, NULL);
1137 else if (conn->type == ACL_LINK)
1138 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1139 6, &conn->dst);
1140 break;
1141 case BT_CONNECT2:
1142 bacpy(&rej.bdaddr, &conn->dst);
1143 rej.reason = 0x15; /* Terminated due to Power Off */
1144 if (conn->type == ACL_LINK)
1145 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1146 sizeof(rej), &rej);
1147 else if (conn->type == SCO_LINK)
1148 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1149 sizeof(rej), &rej);
1150 break;
1151 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001152 }
1153
1154 return hci_req_run(&req, clean_up_hci_complete);
1155}
1156
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001157static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001158 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001159{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001160 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001161 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001162 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Johan Hedberga7e80f22013-01-09 16:05:19 +02001166 if (cp->val != 0x00 && cp->val != 0x01)
1167 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1168 MGMT_STATUS_INVALID_PARAMS);
1169
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001170 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001171
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001172 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1173 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1174 MGMT_STATUS_BUSY);
1175 goto failed;
1176 }
1177
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001178 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1179 cancel_delayed_work(&hdev->power_off);
1180
1181 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001182 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1183 data, len);
1184 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001185 goto failed;
1186 }
1187 }
1188
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001189 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001190 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001191 goto failed;
1192 }
1193
Johan Hedberg03811012010-12-08 00:21:06 +02001194 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1195 if (!cmd) {
1196 err = -ENOMEM;
1197 goto failed;
1198 }
1199
Johan Hedberg8b064a32014-02-24 14:52:22 +02001200 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001201 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001202 err = 0;
1203 } else {
1204 /* Disconnect connections, stop scans, etc */
1205 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001206 if (!err)
1207 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1208 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001209
Johan Hedberg8b064a32014-02-24 14:52:22 +02001210 /* ENODATA means there were no HCI commands queued */
1211 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001212 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001213 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1214 err = 0;
1215 }
1216 }
Johan Hedberg03811012010-12-08 00:21:06 +02001217
1218failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001219 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001220 return err;
1221}
1222
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001223static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1224 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001225{
1226 struct sk_buff *skb;
1227 struct mgmt_hdr *hdr;
1228
Andre Guedes790eff42012-06-07 19:05:46 -03001229 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001230 if (!skb)
1231 return -ENOMEM;
1232
1233 hdr = (void *) skb_put(skb, sizeof(*hdr));
1234 hdr->opcode = cpu_to_le16(event);
1235 if (hdev)
1236 hdr->index = cpu_to_le16(hdev->id);
1237 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001238 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001239 hdr->len = cpu_to_le16(data_len);
1240
1241 if (data)
1242 memcpy(skb_put(skb, data_len), data, data_len);
1243
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001244 /* Time stamp */
1245 __net_timestamp(skb);
1246
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001247 hci_send_to_control(skb, skip_sk);
1248 kfree_skb(skb);
1249
1250 return 0;
1251}
1252
1253static int new_settings(struct hci_dev *hdev, struct sock *skip)
1254{
1255 __le32 ev;
1256
1257 ev = cpu_to_le32(get_current_settings(hdev));
1258
1259 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1260}
1261
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001262struct cmd_lookup {
1263 struct sock *sk;
1264 struct hci_dev *hdev;
1265 u8 mgmt_status;
1266};
1267
1268static void settings_rsp(struct pending_cmd *cmd, void *data)
1269{
1270 struct cmd_lookup *match = data;
1271
1272 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1273
1274 list_del(&cmd->list);
1275
1276 if (match->sk == NULL) {
1277 match->sk = cmd->sk;
1278 sock_hold(match->sk);
1279 }
1280
1281 mgmt_pending_free(cmd);
1282}
1283
1284static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1285{
1286 u8 *status = data;
1287
1288 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1289 mgmt_pending_remove(cmd);
1290}
1291
Johan Hedberge6fe7982013-10-02 15:45:22 +03001292static u8 mgmt_bredr_support(struct hci_dev *hdev)
1293{
1294 if (!lmp_bredr_capable(hdev))
1295 return MGMT_STATUS_NOT_SUPPORTED;
1296 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1297 return MGMT_STATUS_REJECTED;
1298 else
1299 return MGMT_STATUS_SUCCESS;
1300}
1301
1302static u8 mgmt_le_support(struct hci_dev *hdev)
1303{
1304 if (!lmp_le_capable(hdev))
1305 return MGMT_STATUS_NOT_SUPPORTED;
1306 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1307 return MGMT_STATUS_REJECTED;
1308 else
1309 return MGMT_STATUS_SUCCESS;
1310}
1311
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001312static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1313{
1314 struct pending_cmd *cmd;
1315 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001316 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001317 bool changed;
1318
1319 BT_DBG("status 0x%02x", status);
1320
1321 hci_dev_lock(hdev);
1322
1323 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1324 if (!cmd)
1325 goto unlock;
1326
1327 if (status) {
1328 u8 mgmt_err = mgmt_status(status);
1329 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001330 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001331 goto remove_cmd;
1332 }
1333
1334 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001335 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001336 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1337 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001338
1339 if (hdev->discov_timeout > 0) {
1340 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1341 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1342 to);
1343 }
1344 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001345 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1346 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001347 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001348
1349 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1350
1351 if (changed)
1352 new_settings(hdev, cmd->sk);
1353
Marcel Holtmann970ba522013-10-15 06:33:57 -07001354 /* When the discoverable mode gets changed, make sure
1355 * that class of device has the limited discoverable
1356 * bit correctly set.
1357 */
1358 hci_req_init(&req, hdev);
1359 update_class(&req);
1360 hci_req_run(&req, NULL);
1361
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001362remove_cmd:
1363 mgmt_pending_remove(cmd);
1364
1365unlock:
1366 hci_dev_unlock(hdev);
1367}
1368
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001369static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001370 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001371{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001372 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001373 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001374 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001375 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001376 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001377 int err;
1378
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001379 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001380
Johan Hedberg9a43e252013-10-20 19:00:07 +03001381 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1382 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001383 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001384 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001385
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001386 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001387 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1388 MGMT_STATUS_INVALID_PARAMS);
1389
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001390 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001391
1392 /* Disabling discoverable requires that no timeout is set,
1393 * and enabling limited discoverable requires a timeout.
1394 */
1395 if ((cp->val == 0x00 && timeout > 0) ||
1396 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001397 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001398 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001400 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001401
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001402 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001403 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001404 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001405 goto failed;
1406 }
1407
1408 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001409 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001410 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001411 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001412 goto failed;
1413 }
1414
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001415 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001416 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001417 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001418 goto failed;
1419 }
1420
1421 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001422 bool changed = false;
1423
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001424 /* Setting limited discoverable when powered off is
1425 * not a valid operation since it requires a timeout
1426 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1427 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001428 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1429 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1430 changed = true;
1431 }
1432
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001433 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001434 if (err < 0)
1435 goto failed;
1436
1437 if (changed)
1438 err = new_settings(hdev, sk);
1439
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001440 goto failed;
1441 }
1442
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001443 /* If the current mode is the same, then just update the timeout
1444 * value with the new value. And if only the timeout gets updated,
1445 * then no need for any HCI transactions.
1446 */
1447 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1448 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1449 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001450 cancel_delayed_work(&hdev->discov_off);
1451 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001452
Marcel Holtmann36261542013-10-15 08:28:51 -07001453 if (cp->val && hdev->discov_timeout > 0) {
1454 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001455 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001456 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001457 }
1458
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001459 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001460 goto failed;
1461 }
1462
1463 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1464 if (!cmd) {
1465 err = -ENOMEM;
1466 goto failed;
1467 }
1468
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001469 /* Cancel any potential discoverable timeout that might be
1470 * still active and store new timeout value. The arming of
1471 * the timeout happens in the complete handler.
1472 */
1473 cancel_delayed_work(&hdev->discov_off);
1474 hdev->discov_timeout = timeout;
1475
Johan Hedbergb456f872013-10-19 23:38:22 +03001476 /* Limited discoverable mode */
1477 if (cp->val == 0x02)
1478 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1479 else
1480 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1481
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001482 hci_req_init(&req, hdev);
1483
Johan Hedberg9a43e252013-10-20 19:00:07 +03001484 /* The procedure for LE-only controllers is much simpler - just
1485 * update the advertising data.
1486 */
1487 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1488 goto update_ad;
1489
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001490 scan = SCAN_PAGE;
1491
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001492 if (cp->val) {
1493 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001494
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001495 if (cp->val == 0x02) {
1496 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001497 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001498 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1499 hci_cp.iac_lap[1] = 0x8b;
1500 hci_cp.iac_lap[2] = 0x9e;
1501 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1502 hci_cp.iac_lap[4] = 0x8b;
1503 hci_cp.iac_lap[5] = 0x9e;
1504 } else {
1505 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001506 hci_cp.num_iac = 1;
1507 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1508 hci_cp.iac_lap[1] = 0x8b;
1509 hci_cp.iac_lap[2] = 0x9e;
1510 }
1511
1512 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1513 (hci_cp.num_iac * 3) + 1, &hci_cp);
1514
1515 scan |= SCAN_INQUIRY;
1516 } else {
1517 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1518 }
1519
1520 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521
Johan Hedberg9a43e252013-10-20 19:00:07 +03001522update_ad:
1523 update_adv_data(&req);
1524
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001525 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001526 if (err < 0)
1527 mgmt_pending_remove(cmd);
1528
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001529failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001530 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001531 return err;
1532}
1533
Johan Hedberg406d7802013-03-15 17:07:09 -05001534static void write_fast_connectable(struct hci_request *req, bool enable)
1535{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001536 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001537 struct hci_cp_write_page_scan_activity acp;
1538 u8 type;
1539
Johan Hedberg547003b2013-10-21 16:51:53 +03001540 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1541 return;
1542
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001543 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1544 return;
1545
Johan Hedberg406d7802013-03-15 17:07:09 -05001546 if (enable) {
1547 type = PAGE_SCAN_TYPE_INTERLACED;
1548
1549 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001550 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001551 } else {
1552 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1553
1554 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001555 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001556 }
1557
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001558 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001559
Johan Hedbergbd98b992013-03-15 17:07:13 -05001560 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1561 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1562 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1563 sizeof(acp), &acp);
1564
1565 if (hdev->page_scan_type != type)
1566 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001567}
1568
Johan Hedberg2b76f452013-03-15 17:07:04 -05001569static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1570{
1571 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001572 struct mgmt_mode *cp;
1573 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001574
1575 BT_DBG("status 0x%02x", status);
1576
1577 hci_dev_lock(hdev);
1578
1579 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1580 if (!cmd)
1581 goto unlock;
1582
Johan Hedberg37438c12013-10-14 16:20:05 +03001583 if (status) {
1584 u8 mgmt_err = mgmt_status(status);
1585 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1586 goto remove_cmd;
1587 }
1588
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001589 cp = cmd->param;
1590 if (cp->val)
1591 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1592 else
1593 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1594
Johan Hedberg2b76f452013-03-15 17:07:04 -05001595 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1596
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001597 if (changed)
1598 new_settings(hdev, cmd->sk);
1599
Johan Hedberg37438c12013-10-14 16:20:05 +03001600remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001601 mgmt_pending_remove(cmd);
1602
1603unlock:
1604 hci_dev_unlock(hdev);
1605}
1606
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001607static int set_connectable_update_settings(struct hci_dev *hdev,
1608 struct sock *sk, u8 val)
1609{
1610 bool changed = false;
1611 int err;
1612
1613 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1614 changed = true;
1615
1616 if (val) {
1617 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1618 } else {
1619 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1620 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1621 }
1622
1623 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1624 if (err < 0)
1625 return err;
1626
1627 if (changed)
1628 return new_settings(hdev, sk);
1629
1630 return 0;
1631}
1632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001633static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001634 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001635{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001636 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001637 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001638 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001639 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001640 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001642 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001643
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001644 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1645 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001646 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001647 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001648
Johan Hedberga7e80f22013-01-09 16:05:19 +02001649 if (cp->val != 0x00 && cp->val != 0x01)
1650 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1651 MGMT_STATUS_INVALID_PARAMS);
1652
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001653 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001654
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001655 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001656 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001657 goto failed;
1658 }
1659
1660 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001661 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001662 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001663 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001664 goto failed;
1665 }
1666
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001667 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1668 if (!cmd) {
1669 err = -ENOMEM;
1670 goto failed;
1671 }
1672
Johan Hedberg2b76f452013-03-15 17:07:04 -05001673 hci_req_init(&req, hdev);
1674
Johan Hedberg9a43e252013-10-20 19:00:07 +03001675 /* If BR/EDR is not enabled and we disable advertising as a
1676 * by-product of disabling connectable, we need to update the
1677 * advertising flags.
1678 */
1679 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1680 if (!cp->val) {
1681 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1682 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1683 }
1684 update_adv_data(&req);
1685 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001686 if (cp->val) {
1687 scan = SCAN_PAGE;
1688 } else {
1689 scan = 0;
1690
1691 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001692 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001693 cancel_delayed_work(&hdev->discov_off);
1694 }
1695
1696 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1697 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001698
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001699 /* If we're going from non-connectable to connectable or
1700 * vice-versa when fast connectable is enabled ensure that fast
1701 * connectable gets disabled. write_fast_connectable won't do
1702 * anything if the page scan parameters are already what they
1703 * should be.
1704 */
1705 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001706 write_fast_connectable(&req, false);
1707
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001708 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1709 hci_conn_num(hdev, LE_LINK) == 0) {
1710 disable_advertising(&req);
1711 enable_advertising(&req);
1712 }
1713
Johan Hedberg2b76f452013-03-15 17:07:04 -05001714 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001715 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001716 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001717 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001718 err = set_connectable_update_settings(hdev, sk,
1719 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001720 goto failed;
1721 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001722
1723failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001724 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725 return err;
1726}
1727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001728static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001729 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001730{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001731 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001732 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001733 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001735 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001736
Johan Hedberga7e80f22013-01-09 16:05:19 +02001737 if (cp->val != 0x00 && cp->val != 0x01)
1738 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1739 MGMT_STATUS_INVALID_PARAMS);
1740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001742
1743 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001744 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001745 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001746 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001747
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001748 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001749 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001750 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001751
Marcel Holtmann55594352013-10-06 16:11:57 -07001752 if (changed)
1753 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001754
Marcel Holtmann55594352013-10-06 16:11:57 -07001755unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001756 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001757 return err;
1758}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001759
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001760static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1761 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001762{
1763 struct mgmt_mode *cp = data;
1764 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001765 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001766 int err;
1767
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001768 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001769
Johan Hedberge6fe7982013-10-02 15:45:22 +03001770 status = mgmt_bredr_support(hdev);
1771 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001772 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001773 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001774
Johan Hedberga7e80f22013-01-09 16:05:19 +02001775 if (cp->val != 0x00 && cp->val != 0x01)
1776 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1777 MGMT_STATUS_INVALID_PARAMS);
1778
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001779 hci_dev_lock(hdev);
1780
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001781 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001782 bool changed = false;
1783
1784 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001785 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001786 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1787 changed = true;
1788 }
1789
1790 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1791 if (err < 0)
1792 goto failed;
1793
1794 if (changed)
1795 err = new_settings(hdev, sk);
1796
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001797 goto failed;
1798 }
1799
1800 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001801 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001802 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001803 goto failed;
1804 }
1805
1806 val = !!cp->val;
1807
1808 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1809 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1810 goto failed;
1811 }
1812
1813 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1814 if (!cmd) {
1815 err = -ENOMEM;
1816 goto failed;
1817 }
1818
1819 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1820 if (err < 0) {
1821 mgmt_pending_remove(cmd);
1822 goto failed;
1823 }
1824
1825failed:
1826 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001827 return err;
1828}
1829
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001830static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001831{
1832 struct mgmt_mode *cp = data;
1833 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001834 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001835 int err;
1836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001837 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001838
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001839 status = mgmt_bredr_support(hdev);
1840 if (status)
1841 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1842
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001843 if (!lmp_ssp_capable(hdev))
1844 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1845 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001846
Johan Hedberga7e80f22013-01-09 16:05:19 +02001847 if (cp->val != 0x00 && cp->val != 0x01)
1848 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1849 MGMT_STATUS_INVALID_PARAMS);
1850
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001851 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001852
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001853 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001854 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001855
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001856 if (cp->val) {
1857 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1858 &hdev->dev_flags);
1859 } else {
1860 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1861 &hdev->dev_flags);
1862 if (!changed)
1863 changed = test_and_clear_bit(HCI_HS_ENABLED,
1864 &hdev->dev_flags);
1865 else
1866 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001867 }
1868
1869 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1870 if (err < 0)
1871 goto failed;
1872
1873 if (changed)
1874 err = new_settings(hdev, sk);
1875
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001876 goto failed;
1877 }
1878
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001879 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1880 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001881 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1882 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001883 goto failed;
1884 }
1885
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001886 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001887 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1888 goto failed;
1889 }
1890
1891 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1892 if (!cmd) {
1893 err = -ENOMEM;
1894 goto failed;
1895 }
1896
Johan Hedberg37699722014-06-24 14:00:27 +03001897 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1898 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1899 sizeof(cp->val), &cp->val);
1900
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001901 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001902 if (err < 0) {
1903 mgmt_pending_remove(cmd);
1904 goto failed;
1905 }
1906
1907failed:
1908 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001909 return err;
1910}
1911
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001912static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001913{
1914 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001915 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001916 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001917 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001918
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001919 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001920
Johan Hedberge6fe7982013-10-02 15:45:22 +03001921 status = mgmt_bredr_support(hdev);
1922 if (status)
1923 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001924
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001925 if (!lmp_ssp_capable(hdev))
1926 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1927 MGMT_STATUS_NOT_SUPPORTED);
1928
1929 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1930 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1931 MGMT_STATUS_REJECTED);
1932
Johan Hedberga7e80f22013-01-09 16:05:19 +02001933 if (cp->val != 0x00 && cp->val != 0x01)
1934 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1935 MGMT_STATUS_INVALID_PARAMS);
1936
Marcel Holtmannee392692013-10-01 22:59:23 -07001937 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001938
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001939 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001940 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001941 } else {
1942 if (hdev_is_powered(hdev)) {
1943 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1944 MGMT_STATUS_REJECTED);
1945 goto unlock;
1946 }
1947
Marcel Holtmannee392692013-10-01 22:59:23 -07001948 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001949 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001950
1951 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1952 if (err < 0)
1953 goto unlock;
1954
1955 if (changed)
1956 err = new_settings(hdev, sk);
1957
1958unlock:
1959 hci_dev_unlock(hdev);
1960 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001961}
1962
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001963static void le_enable_complete(struct hci_dev *hdev, u8 status)
1964{
1965 struct cmd_lookup match = { NULL, hdev };
1966
1967 if (status) {
1968 u8 mgmt_err = mgmt_status(status);
1969
1970 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1971 &mgmt_err);
1972 return;
1973 }
1974
1975 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1976
1977 new_settings(hdev, match.sk);
1978
1979 if (match.sk)
1980 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001981
1982 /* Make sure the controller has a good default for
1983 * advertising data. Restrict the update to when LE
1984 * has actually been enabled. During power on, the
1985 * update in powered_update_hci will take care of it.
1986 */
1987 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1988 struct hci_request req;
1989
1990 hci_dev_lock(hdev);
1991
1992 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001993 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001994 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001995 hci_req_run(&req, NULL);
1996
1997 hci_dev_unlock(hdev);
1998 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001999}
2000
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002001static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002002{
2003 struct mgmt_mode *cp = data;
2004 struct hci_cp_write_le_host_supported hci_cp;
2005 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002006 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002007 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002008 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002009
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002010 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002011
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002012 if (!lmp_le_capable(hdev))
2013 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2014 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002015
Johan Hedberga7e80f22013-01-09 16:05:19 +02002016 if (cp->val != 0x00 && cp->val != 0x01)
2017 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2018 MGMT_STATUS_INVALID_PARAMS);
2019
Johan Hedbergc73eee92013-04-19 18:35:21 +03002020 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002021 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002022 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2023 MGMT_STATUS_REJECTED);
2024
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002025 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002026
2027 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002028 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002029
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002030 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002031 bool changed = false;
2032
2033 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2034 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2035 changed = true;
2036 }
2037
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002038 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2039 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002040 changed = true;
2041 }
2042
Johan Hedberg06199cf2012-02-22 16:37:11 +02002043 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2044 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002045 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002046
2047 if (changed)
2048 err = new_settings(hdev, sk);
2049
Johan Hedberg1de028c2012-02-29 19:55:35 -08002050 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002051 }
2052
Johan Hedberg4375f102013-09-25 13:26:10 +03002053 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2054 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002055 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002056 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002057 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002058 }
2059
2060 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2061 if (!cmd) {
2062 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002063 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002064 }
2065
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002066 hci_req_init(&req, hdev);
2067
Johan Hedberg06199cf2012-02-22 16:37:11 +02002068 memset(&hci_cp, 0, sizeof(hci_cp));
2069
2070 if (val) {
2071 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002072 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002073 } else {
2074 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2075 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002076 }
2077
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002078 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2079 &hci_cp);
2080
2081 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302082 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002083 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002084
Johan Hedberg1de028c2012-02-29 19:55:35 -08002085unlock:
2086 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002087 return err;
2088}
2089
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002090/* This is a helper function to test for pending mgmt commands that can
2091 * cause CoD or EIR HCI commands. We can only allow one such pending
2092 * mgmt command at a time since otherwise we cannot easily track what
2093 * the current values are, will be, and based on that calculate if a new
2094 * HCI command needs to be sent and if yes with what value.
2095 */
2096static bool pending_eir_or_class(struct hci_dev *hdev)
2097{
2098 struct pending_cmd *cmd;
2099
2100 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2101 switch (cmd->opcode) {
2102 case MGMT_OP_ADD_UUID:
2103 case MGMT_OP_REMOVE_UUID:
2104 case MGMT_OP_SET_DEV_CLASS:
2105 case MGMT_OP_SET_POWERED:
2106 return true;
2107 }
2108 }
2109
2110 return false;
2111}
2112
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002113static const u8 bluetooth_base_uuid[] = {
2114 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2115 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2116};
2117
2118static u8 get_uuid_size(const u8 *uuid)
2119{
2120 u32 val;
2121
2122 if (memcmp(uuid, bluetooth_base_uuid, 12))
2123 return 128;
2124
2125 val = get_unaligned_le32(&uuid[12]);
2126 if (val > 0xffff)
2127 return 32;
2128
2129 return 16;
2130}
2131
Johan Hedberg92da6092013-03-15 17:06:55 -05002132static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2133{
2134 struct pending_cmd *cmd;
2135
2136 hci_dev_lock(hdev);
2137
2138 cmd = mgmt_pending_find(mgmt_op, hdev);
2139 if (!cmd)
2140 goto unlock;
2141
2142 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2143 hdev->dev_class, 3);
2144
2145 mgmt_pending_remove(cmd);
2146
2147unlock:
2148 hci_dev_unlock(hdev);
2149}
2150
2151static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2152{
2153 BT_DBG("status 0x%02x", status);
2154
2155 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2156}
2157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002158static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002159{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002160 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002161 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002162 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002163 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002164 int err;
2165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002166 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002167
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002168 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002169
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002170 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002171 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002172 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002173 goto failed;
2174 }
2175
Andre Guedes92c4c202012-06-07 19:05:44 -03002176 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002177 if (!uuid) {
2178 err = -ENOMEM;
2179 goto failed;
2180 }
2181
2182 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002183 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002184 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002185
Johan Hedbergde66aa62013-01-27 00:31:27 +02002186 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002187
Johan Hedberg890ea892013-03-15 17:06:52 -05002188 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002189
Johan Hedberg890ea892013-03-15 17:06:52 -05002190 update_class(&req);
2191 update_eir(&req);
2192
Johan Hedberg92da6092013-03-15 17:06:55 -05002193 err = hci_req_run(&req, add_uuid_complete);
2194 if (err < 0) {
2195 if (err != -ENODATA)
2196 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002198 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002199 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002200 goto failed;
2201 }
2202
2203 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002204 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002205 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002206 goto failed;
2207 }
2208
2209 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002210
2211failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002212 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002213 return err;
2214}
2215
Johan Hedberg24b78d02012-02-23 23:24:30 +02002216static bool enable_service_cache(struct hci_dev *hdev)
2217{
2218 if (!hdev_is_powered(hdev))
2219 return false;
2220
2221 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002222 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2223 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002224 return true;
2225 }
2226
2227 return false;
2228}
2229
Johan Hedberg92da6092013-03-15 17:06:55 -05002230static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2231{
2232 BT_DBG("status 0x%02x", status);
2233
2234 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2235}
2236
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002237static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002238 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002239{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002240 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002241 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002242 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002243 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 -05002244 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002245 int err, found;
2246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002248
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002249 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002250
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002251 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002252 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002253 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002254 goto unlock;
2255 }
2256
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002257 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002258 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002259
Johan Hedberg24b78d02012-02-23 23:24:30 +02002260 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002261 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002262 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002263 goto unlock;
2264 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002265
Johan Hedberg9246a862012-02-23 21:33:16 +02002266 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002267 }
2268
2269 found = 0;
2270
Johan Hedberg056341c2013-01-27 00:31:30 +02002271 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002272 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2273 continue;
2274
2275 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002276 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002277 found++;
2278 }
2279
2280 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002281 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002282 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002283 goto unlock;
2284 }
2285
Johan Hedberg9246a862012-02-23 21:33:16 +02002286update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002287 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002288
Johan Hedberg890ea892013-03-15 17:06:52 -05002289 update_class(&req);
2290 update_eir(&req);
2291
Johan Hedberg92da6092013-03-15 17:06:55 -05002292 err = hci_req_run(&req, remove_uuid_complete);
2293 if (err < 0) {
2294 if (err != -ENODATA)
2295 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002297 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002298 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002299 goto unlock;
2300 }
2301
2302 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002303 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002304 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002305 goto unlock;
2306 }
2307
2308 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002309
2310unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002311 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002312 return err;
2313}
2314
Johan Hedberg92da6092013-03-15 17:06:55 -05002315static void set_class_complete(struct hci_dev *hdev, u8 status)
2316{
2317 BT_DBG("status 0x%02x", status);
2318
2319 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2320}
2321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002322static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002323 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002324{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002325 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002326 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002327 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002328 int err;
2329
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002330 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002332 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002333 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2334 MGMT_STATUS_NOT_SUPPORTED);
2335
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002336 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002337
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002338 if (pending_eir_or_class(hdev)) {
2339 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2340 MGMT_STATUS_BUSY);
2341 goto unlock;
2342 }
2343
2344 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2345 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2346 MGMT_STATUS_INVALID_PARAMS);
2347 goto unlock;
2348 }
2349
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002350 hdev->major_class = cp->major;
2351 hdev->minor_class = cp->minor;
2352
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002353 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002354 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002355 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002356 goto unlock;
2357 }
2358
Johan Hedberg890ea892013-03-15 17:06:52 -05002359 hci_req_init(&req, hdev);
2360
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002361 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002362 hci_dev_unlock(hdev);
2363 cancel_delayed_work_sync(&hdev->service_cache);
2364 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002365 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002366 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002367
Johan Hedberg890ea892013-03-15 17:06:52 -05002368 update_class(&req);
2369
Johan Hedberg92da6092013-03-15 17:06:55 -05002370 err = hci_req_run(&req, set_class_complete);
2371 if (err < 0) {
2372 if (err != -ENODATA)
2373 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002374
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002375 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002376 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002377 goto unlock;
2378 }
2379
2380 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002381 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002382 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002383 goto unlock;
2384 }
2385
2386 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002387
Johan Hedbergb5235a62012-02-21 14:32:24 +02002388unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002389 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002390 return err;
2391}
2392
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002394 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002395{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002396 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002397 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002398 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002399 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002400
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002401 BT_DBG("request for %s", hdev->name);
2402
2403 if (!lmp_bredr_capable(hdev))
2404 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2405 MGMT_STATUS_NOT_SUPPORTED);
2406
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002407 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002408
Johan Hedberg86742e12011-11-07 23:13:38 +02002409 expected_len = sizeof(*cp) + key_count *
2410 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002411 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002412 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002413 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002415 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002416 }
2417
Johan Hedberg4ae143012013-01-20 14:27:13 +02002418 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2419 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2420 MGMT_STATUS_INVALID_PARAMS);
2421
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002422 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002423 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002424
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002425 for (i = 0; i < key_count; i++) {
2426 struct mgmt_link_key_info *key = &cp->keys[i];
2427
Marcel Holtmann8e991132014-01-10 02:07:25 -08002428 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002429 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2430 MGMT_STATUS_INVALID_PARAMS);
2431 }
2432
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002433 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002434
2435 hci_link_keys_clear(hdev);
2436
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002437 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002438 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2439 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002440 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002441 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2442 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002443
2444 if (changed)
2445 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002446
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002447 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002448 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002449
Johan Hedberg58e92932014-06-24 14:00:26 +03002450 /* Always ignore debug keys and require a new pairing if
2451 * the user wants to use them.
2452 */
2453 if (key->type == HCI_LK_DEBUG_COMBINATION)
2454 continue;
2455
Johan Hedberg7652ff62014-06-24 13:15:49 +03002456 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2457 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002458 }
2459
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002460 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002461
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002462 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002463
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002464 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002465}
2466
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002467static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002468 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002469{
2470 struct mgmt_ev_device_unpaired ev;
2471
2472 bacpy(&ev.addr.bdaddr, bdaddr);
2473 ev.addr.type = addr_type;
2474
2475 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002476 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002477}
2478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002479static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002480 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002481{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002482 struct mgmt_cp_unpair_device *cp = data;
2483 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002484 struct hci_cp_disconnect dc;
2485 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002486 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002487 int err;
2488
Johan Hedberga8a1d192011-11-10 15:54:38 +02002489 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002490 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2491 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002492
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002493 if (!bdaddr_type_is_valid(cp->addr.type))
2494 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2495 MGMT_STATUS_INVALID_PARAMS,
2496 &rp, sizeof(rp));
2497
Johan Hedberg118da702013-01-20 14:27:20 +02002498 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2499 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2500 MGMT_STATUS_INVALID_PARAMS,
2501 &rp, sizeof(rp));
2502
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002503 hci_dev_lock(hdev);
2504
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002505 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002506 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002507 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002508 goto unlock;
2509 }
2510
Johan Hedberge0b2b272014-02-18 17:14:31 +02002511 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002512 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002513 } else {
2514 u8 addr_type;
2515
2516 if (cp->addr.type == BDADDR_LE_PUBLIC)
2517 addr_type = ADDR_LE_DEV_PUBLIC;
2518 else
2519 addr_type = ADDR_LE_DEV_RANDOM;
2520
Johan Hedberga7ec7332014-02-18 17:14:35 +02002521 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2522
Andre Guedesa9b0a042014-02-26 20:21:52 -03002523 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2524
Johan Hedberge0b2b272014-02-18 17:14:31 +02002525 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2526 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002527
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002528 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002529 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002530 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002531 goto unlock;
2532 }
2533
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002534 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002535 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002536 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002537 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002538 else
2539 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002540 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002541 } else {
2542 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002543 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002544
Johan Hedberga8a1d192011-11-10 15:54:38 +02002545 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002546 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002547 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002548 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002549 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002550 }
2551
Johan Hedberg124f6e32012-02-09 13:50:12 +02002552 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002553 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002554 if (!cmd) {
2555 err = -ENOMEM;
2556 goto unlock;
2557 }
2558
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002559 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002560 dc.reason = 0x13; /* Remote User Terminated Connection */
2561 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2562 if (err < 0)
2563 mgmt_pending_remove(cmd);
2564
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002565unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002566 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002567 return err;
2568}
2569
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002570static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002571 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002572{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002573 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002574 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002576 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002577 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002578 int err;
2579
2580 BT_DBG("");
2581
Johan Hedberg06a63b12013-01-20 14:27:21 +02002582 memset(&rp, 0, sizeof(rp));
2583 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2584 rp.addr.type = cp->addr.type;
2585
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002586 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002587 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2588 MGMT_STATUS_INVALID_PARAMS,
2589 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002591 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002592
2593 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002594 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2595 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002596 goto failed;
2597 }
2598
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002599 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002600 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2601 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002602 goto failed;
2603 }
2604
Andre Guedes591f47f2012-04-24 21:02:49 -03002605 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002606 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2607 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002608 else
2609 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002610
Vishal Agarwalf9607272012-06-13 05:32:43 +05302611 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2613 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002614 goto failed;
2615 }
2616
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002617 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002618 if (!cmd) {
2619 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002620 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002621 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002622
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002623 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002624 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002625
2626 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2627 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002628 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002629
2630failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002631 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002632 return err;
2633}
2634
Andre Guedes57c14772012-04-24 21:02:50 -03002635static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002636{
2637 switch (link_type) {
2638 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002639 switch (addr_type) {
2640 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002641 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002642
Johan Hedberg48264f02011-11-09 13:58:58 +02002643 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002644 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002645 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002646 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002647
Johan Hedberg4c659c32011-11-07 23:13:39 +02002648 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002649 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002650 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002651 }
2652}
2653
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002654static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2655 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002656{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002657 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002658 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002659 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002660 int err;
2661 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002662
2663 BT_DBG("");
2664
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002665 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002666
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002667 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002668 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002669 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002670 goto unlock;
2671 }
2672
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002673 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002674 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2675 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002676 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002677 }
2678
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002679 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002680 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002681 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002682 err = -ENOMEM;
2683 goto unlock;
2684 }
2685
Johan Hedberg2784eb42011-01-21 13:56:35 +02002686 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002687 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002688 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2689 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002690 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002691 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002692 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002693 continue;
2694 i++;
2695 }
2696
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002697 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002698
Johan Hedberg4c659c32011-11-07 23:13:39 +02002699 /* Recalculate length in case of filtered SCO connections, etc */
2700 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002702 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002703 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002704
Johan Hedberga38528f2011-01-22 06:46:43 +02002705 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002706
2707unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002708 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002709 return err;
2710}
2711
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002712static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002714{
2715 struct pending_cmd *cmd;
2716 int err;
2717
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002718 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002719 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002720 if (!cmd)
2721 return -ENOMEM;
2722
Johan Hedbergd8457692012-02-17 14:24:57 +02002723 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002724 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002725 if (err < 0)
2726 mgmt_pending_remove(cmd);
2727
2728 return err;
2729}
2730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002731static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002733{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002734 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002735 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002736 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002737 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002738 int err;
2739
2740 BT_DBG("");
2741
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002742 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002743
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002744 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002745 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002746 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002747 goto failed;
2748 }
2749
Johan Hedbergd8457692012-02-17 14:24:57 +02002750 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002751 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002752 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002753 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002754 goto failed;
2755 }
2756
2757 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002758 struct mgmt_cp_pin_code_neg_reply ncp;
2759
2760 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002761
2762 BT_ERR("PIN code is not 16 bytes long");
2763
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002764 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002765 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002766 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002767 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002768
2769 goto failed;
2770 }
2771
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002772 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002773 if (!cmd) {
2774 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002775 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002776 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002777
Johan Hedbergd8457692012-02-17 14:24:57 +02002778 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002779 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002780 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002781
2782 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2783 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002784 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002785
2786failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002787 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002788 return err;
2789}
2790
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002791static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2792 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002793{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002794 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002795
2796 BT_DBG("");
2797
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002798 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2799 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2800 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2801
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002802 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002803
2804 hdev->io_capability = cp->io_capability;
2805
2806 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002807 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002808
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002809 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002810
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002811 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2812 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002813}
2814
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002815static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002816{
2817 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002818 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002819
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002820 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002821 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2822 continue;
2823
Johan Hedberge9a416b2011-02-19 12:05:56 -03002824 if (cmd->user_data != conn)
2825 continue;
2826
2827 return cmd;
2828 }
2829
2830 return NULL;
2831}
2832
2833static void pairing_complete(struct pending_cmd *cmd, u8 status)
2834{
2835 struct mgmt_rp_pair_device rp;
2836 struct hci_conn *conn = cmd->user_data;
2837
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002838 bacpy(&rp.addr.bdaddr, &conn->dst);
2839 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002840
Johan Hedbergaee9b212012-02-18 15:07:59 +02002841 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002842 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002843
2844 /* So we don't get further callbacks for this connection */
2845 conn->connect_cfm_cb = NULL;
2846 conn->security_cfm_cb = NULL;
2847 conn->disconn_cfm_cb = NULL;
2848
David Herrmann76a68ba2013-04-06 20:28:37 +02002849 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002850
Johan Hedberga664b5b2011-02-19 12:06:02 -03002851 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002852}
2853
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002854void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2855{
2856 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2857 struct pending_cmd *cmd;
2858
2859 cmd = find_pairing(conn);
2860 if (cmd)
2861 pairing_complete(cmd, status);
2862}
2863
Johan Hedberge9a416b2011-02-19 12:05:56 -03002864static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2865{
2866 struct pending_cmd *cmd;
2867
2868 BT_DBG("status %u", status);
2869
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002870 cmd = find_pairing(conn);
2871 if (!cmd)
2872 BT_DBG("Unable to find a pending command");
2873 else
Johan Hedberge2113262012-02-18 15:20:03 +02002874 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002875}
2876
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002877static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302878{
2879 struct pending_cmd *cmd;
2880
2881 BT_DBG("status %u", status);
2882
2883 if (!status)
2884 return;
2885
2886 cmd = find_pairing(conn);
2887 if (!cmd)
2888 BT_DBG("Unable to find a pending command");
2889 else
2890 pairing_complete(cmd, mgmt_status(status));
2891}
2892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002893static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002894 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002895{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002896 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002897 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002898 struct pending_cmd *cmd;
2899 u8 sec_level, auth_type;
2900 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002901 int err;
2902
2903 BT_DBG("");
2904
Szymon Jancf950a30e2013-01-18 12:48:07 +01002905 memset(&rp, 0, sizeof(rp));
2906 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2907 rp.addr.type = cp->addr.type;
2908
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002909 if (!bdaddr_type_is_valid(cp->addr.type))
2910 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2911 MGMT_STATUS_INVALID_PARAMS,
2912 &rp, sizeof(rp));
2913
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002914 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2915 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2916 MGMT_STATUS_INVALID_PARAMS,
2917 &rp, sizeof(rp));
2918
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002919 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002920
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002921 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002922 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2923 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002924 goto unlock;
2925 }
2926
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002927 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002928 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002929
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002930 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002931 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2932 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002933 } else {
2934 u8 addr_type;
2935
2936 /* Convert from L2CAP channel address type to HCI address type
2937 */
2938 if (cp->addr.type == BDADDR_LE_PUBLIC)
2939 addr_type = ADDR_LE_DEV_PUBLIC;
2940 else
2941 addr_type = ADDR_LE_DEV_RANDOM;
2942
2943 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002944 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002945 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002946
Ville Tervo30e76272011-02-22 16:10:53 -03002947 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002948 int status;
2949
2950 if (PTR_ERR(conn) == -EBUSY)
2951 status = MGMT_STATUS_BUSY;
2952 else
2953 status = MGMT_STATUS_CONNECT_FAILED;
2954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002955 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002956 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002957 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002958 goto unlock;
2959 }
2960
2961 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002962 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002963 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002964 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002965 goto unlock;
2966 }
2967
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002968 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002969 if (!cmd) {
2970 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002971 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002972 goto unlock;
2973 }
2974
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002975 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002976 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002977 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002978 conn->security_cfm_cb = pairing_complete_cb;
2979 conn->disconn_cfm_cb = pairing_complete_cb;
2980 } else {
2981 conn->connect_cfm_cb = le_pairing_complete_cb;
2982 conn->security_cfm_cb = le_pairing_complete_cb;
2983 conn->disconn_cfm_cb = le_pairing_complete_cb;
2984 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002985
Johan Hedberge9a416b2011-02-19 12:05:56 -03002986 conn->io_capability = cp->io_cap;
2987 cmd->user_data = conn;
2988
2989 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002990 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002991 pairing_complete(cmd, 0);
2992
2993 err = 0;
2994
2995unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002996 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002997 return err;
2998}
2999
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3001 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003002{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003003 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003004 struct pending_cmd *cmd;
3005 struct hci_conn *conn;
3006 int err;
3007
3008 BT_DBG("");
3009
Johan Hedberg28424702012-02-02 04:02:29 +02003010 hci_dev_lock(hdev);
3011
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003012 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003013 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003014 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003015 goto unlock;
3016 }
3017
Johan Hedberg28424702012-02-02 04:02:29 +02003018 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3019 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003020 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003021 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003022 goto unlock;
3023 }
3024
3025 conn = cmd->user_data;
3026
3027 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003028 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003029 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003030 goto unlock;
3031 }
3032
3033 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003035 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003036 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003037unlock:
3038 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003039 return err;
3040}
3041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003043 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003044 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003045{
Johan Hedberga5c29682011-02-19 12:05:57 -03003046 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003047 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003048 int err;
3049
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003050 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003051
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003052 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003053 err = cmd_complete(sk, hdev->id, mgmt_op,
3054 MGMT_STATUS_NOT_POWERED, addr,
3055 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003056 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003057 }
3058
Johan Hedberg1707c602013-03-15 17:07:15 -05003059 if (addr->type == BDADDR_BREDR)
3060 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003061 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003062 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003063
Johan Hedberg272d90d2012-02-09 15:26:12 +02003064 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003065 err = cmd_complete(sk, hdev->id, mgmt_op,
3066 MGMT_STATUS_NOT_CONNECTED, addr,
3067 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003068 goto done;
3069 }
3070
Johan Hedberg1707c602013-03-15 17:07:15 -05003071 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003072 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003073 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003074 err = cmd_complete(sk, hdev->id, mgmt_op,
3075 MGMT_STATUS_SUCCESS, addr,
3076 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003077 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003078 err = cmd_complete(sk, hdev->id, mgmt_op,
3079 MGMT_STATUS_FAILED, addr,
3080 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003081
Brian Gix47c15e22011-11-16 13:53:14 -08003082 goto done;
3083 }
3084
Johan Hedberg1707c602013-03-15 17:07:15 -05003085 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003086 if (!cmd) {
3087 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003088 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003089 }
3090
Brian Gix0df4c182011-11-16 13:53:13 -08003091 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003092 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3093 struct hci_cp_user_passkey_reply cp;
3094
Johan Hedberg1707c602013-03-15 17:07:15 -05003095 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003096 cp.passkey = passkey;
3097 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3098 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003099 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3100 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003101
Johan Hedberga664b5b2011-02-19 12:06:02 -03003102 if (err < 0)
3103 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003104
Brian Gix0df4c182011-11-16 13:53:13 -08003105done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003106 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003107 return err;
3108}
3109
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303110static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3111 void *data, u16 len)
3112{
3113 struct mgmt_cp_pin_code_neg_reply *cp = data;
3114
3115 BT_DBG("");
3116
Johan Hedberg1707c602013-03-15 17:07:15 -05003117 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303118 MGMT_OP_PIN_CODE_NEG_REPLY,
3119 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3120}
3121
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003122static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3123 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003124{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003125 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003126
3127 BT_DBG("");
3128
3129 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003130 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003131 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003132
Johan Hedberg1707c602013-03-15 17:07:15 -05003133 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003134 MGMT_OP_USER_CONFIRM_REPLY,
3135 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003136}
3137
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003138static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003139 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003140{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003141 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003142
3143 BT_DBG("");
3144
Johan Hedberg1707c602013-03-15 17:07:15 -05003145 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003146 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3147 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003148}
3149
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003150static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3151 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003152{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003153 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003154
3155 BT_DBG("");
3156
Johan Hedberg1707c602013-03-15 17:07:15 -05003157 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003158 MGMT_OP_USER_PASSKEY_REPLY,
3159 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003160}
3161
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003162static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003163 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003164{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003165 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003166
3167 BT_DBG("");
3168
Johan Hedberg1707c602013-03-15 17:07:15 -05003169 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003170 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3171 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003172}
3173
Johan Hedberg13928972013-03-15 17:07:00 -05003174static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003175{
Johan Hedberg13928972013-03-15 17:07:00 -05003176 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003177 struct hci_cp_write_local_name cp;
3178
Johan Hedberg13928972013-03-15 17:07:00 -05003179 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003180
Johan Hedberg890ea892013-03-15 17:06:52 -05003181 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003182}
3183
Johan Hedberg13928972013-03-15 17:07:00 -05003184static void set_name_complete(struct hci_dev *hdev, u8 status)
3185{
3186 struct mgmt_cp_set_local_name *cp;
3187 struct pending_cmd *cmd;
3188
3189 BT_DBG("status 0x%02x", status);
3190
3191 hci_dev_lock(hdev);
3192
3193 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3194 if (!cmd)
3195 goto unlock;
3196
3197 cp = cmd->param;
3198
3199 if (status)
3200 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3201 mgmt_status(status));
3202 else
3203 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3204 cp, sizeof(*cp));
3205
3206 mgmt_pending_remove(cmd);
3207
3208unlock:
3209 hci_dev_unlock(hdev);
3210}
3211
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003212static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003213 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003214{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003215 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003216 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003217 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003218 int err;
3219
3220 BT_DBG("");
3221
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003222 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003223
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003224 /* If the old values are the same as the new ones just return a
3225 * direct command complete event.
3226 */
3227 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3228 !memcmp(hdev->short_name, cp->short_name,
3229 sizeof(hdev->short_name))) {
3230 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3231 data, len);
3232 goto failed;
3233 }
3234
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003235 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003236
Johan Hedbergb5235a62012-02-21 14:32:24 +02003237 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003238 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003239
3240 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003241 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003242 if (err < 0)
3243 goto failed;
3244
3245 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003246 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003247
Johan Hedbergb5235a62012-02-21 14:32:24 +02003248 goto failed;
3249 }
3250
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003251 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003252 if (!cmd) {
3253 err = -ENOMEM;
3254 goto failed;
3255 }
3256
Johan Hedberg13928972013-03-15 17:07:00 -05003257 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3258
Johan Hedberg890ea892013-03-15 17:06:52 -05003259 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003260
3261 if (lmp_bredr_capable(hdev)) {
3262 update_name(&req);
3263 update_eir(&req);
3264 }
3265
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003266 /* The name is stored in the scan response data and so
3267 * no need to udpate the advertising data here.
3268 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003269 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003270 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003271
Johan Hedberg13928972013-03-15 17:07:00 -05003272 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003273 if (err < 0)
3274 mgmt_pending_remove(cmd);
3275
3276failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003277 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003278 return err;
3279}
3280
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003281static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003282 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003283{
Szymon Jancc35938b2011-03-22 13:12:21 +01003284 struct pending_cmd *cmd;
3285 int err;
3286
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003287 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003288
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003289 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003290
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003291 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003292 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003293 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003294 goto unlock;
3295 }
3296
Andre Guedes9a1a1992012-07-24 15:03:48 -03003297 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003298 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003299 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003300 goto unlock;
3301 }
3302
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003303 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003304 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003305 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003306 goto unlock;
3307 }
3308
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003309 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003310 if (!cmd) {
3311 err = -ENOMEM;
3312 goto unlock;
3313 }
3314
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003315 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3316 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3317 0, NULL);
3318 else
3319 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3320
Szymon Jancc35938b2011-03-22 13:12:21 +01003321 if (err < 0)
3322 mgmt_pending_remove(cmd);
3323
3324unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003325 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003326 return err;
3327}
3328
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003329static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003330 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003331{
Szymon Janc2763eda2011-03-22 13:12:22 +01003332 int err;
3333
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003334 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003335
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003336 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003337
Marcel Holtmannec109112014-01-10 02:07:30 -08003338 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3339 struct mgmt_cp_add_remote_oob_data *cp = data;
3340 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003341
Marcel Holtmannec109112014-01-10 02:07:30 -08003342 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3343 cp->hash, cp->randomizer);
3344 if (err < 0)
3345 status = MGMT_STATUS_FAILED;
3346 else
3347 status = MGMT_STATUS_SUCCESS;
3348
3349 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3350 status, &cp->addr, sizeof(cp->addr));
3351 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3352 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3353 u8 status;
3354
3355 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3356 cp->hash192,
3357 cp->randomizer192,
3358 cp->hash256,
3359 cp->randomizer256);
3360 if (err < 0)
3361 status = MGMT_STATUS_FAILED;
3362 else
3363 status = MGMT_STATUS_SUCCESS;
3364
3365 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3366 status, &cp->addr, sizeof(cp->addr));
3367 } else {
3368 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3369 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3370 MGMT_STATUS_INVALID_PARAMS);
3371 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003372
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003373 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003374 return err;
3375}
3376
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003377static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003378 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003379{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003380 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003381 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003382 int err;
3383
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003384 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003385
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003386 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003387
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003388 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003389 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003390 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003391 else
Szymon Janca6785be2012-12-13 15:11:21 +01003392 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003393
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003394 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003395 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003396
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003397 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003398 return err;
3399}
3400
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003401static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3402{
3403 struct pending_cmd *cmd;
3404 u8 type;
3405 int err;
3406
3407 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3408
3409 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3410 if (!cmd)
3411 return -ENOENT;
3412
3413 type = hdev->discovery.type;
3414
3415 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3416 &type, sizeof(type));
3417 mgmt_pending_remove(cmd);
3418
3419 return err;
3420}
3421
Andre Guedes7c307722013-04-30 15:29:28 -03003422static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3423{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003424 unsigned long timeout = 0;
3425
Andre Guedes7c307722013-04-30 15:29:28 -03003426 BT_DBG("status %d", status);
3427
3428 if (status) {
3429 hci_dev_lock(hdev);
3430 mgmt_start_discovery_failed(hdev, status);
3431 hci_dev_unlock(hdev);
3432 return;
3433 }
3434
3435 hci_dev_lock(hdev);
3436 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3437 hci_dev_unlock(hdev);
3438
3439 switch (hdev->discovery.type) {
3440 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003441 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003442 break;
3443
3444 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003445 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003446 break;
3447
3448 case DISCOV_TYPE_BREDR:
3449 break;
3450
3451 default:
3452 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3453 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003454
3455 if (!timeout)
3456 return;
3457
3458 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003459}
3460
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003461static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003462 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003463{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003464 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003465 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003466 struct hci_cp_le_set_scan_param param_cp;
3467 struct hci_cp_le_set_scan_enable enable_cp;
3468 struct hci_cp_inquiry inq_cp;
3469 struct hci_request req;
3470 /* General inquiry access code (GIAC) */
3471 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003472 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003473 int err;
3474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003475 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003476
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003477 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003478
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003479 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003480 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003481 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003482 goto failed;
3483 }
3484
Andre Guedes642be6c2012-03-21 00:03:37 -03003485 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3486 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3487 MGMT_STATUS_BUSY);
3488 goto failed;
3489 }
3490
Johan Hedbergff9ef572012-01-04 14:23:45 +02003491 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003492 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003493 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003494 goto failed;
3495 }
3496
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003497 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003498 if (!cmd) {
3499 err = -ENOMEM;
3500 goto failed;
3501 }
3502
Andre Guedes4aab14e2012-02-17 20:39:36 -03003503 hdev->discovery.type = cp->type;
3504
Andre Guedes7c307722013-04-30 15:29:28 -03003505 hci_req_init(&req, hdev);
3506
Andre Guedes4aab14e2012-02-17 20:39:36 -03003507 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003508 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003509 status = mgmt_bredr_support(hdev);
3510 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003511 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003512 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003513 mgmt_pending_remove(cmd);
3514 goto failed;
3515 }
3516
Andre Guedes7c307722013-04-30 15:29:28 -03003517 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3518 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3519 MGMT_STATUS_BUSY);
3520 mgmt_pending_remove(cmd);
3521 goto failed;
3522 }
3523
3524 hci_inquiry_cache_flush(hdev);
3525
3526 memset(&inq_cp, 0, sizeof(inq_cp));
3527 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003528 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003529 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003530 break;
3531
3532 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003533 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003534 status = mgmt_le_support(hdev);
3535 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003536 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003537 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003538 mgmt_pending_remove(cmd);
3539 goto failed;
3540 }
3541
Andre Guedes7c307722013-04-30 15:29:28 -03003542 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003543 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003544 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3545 MGMT_STATUS_NOT_SUPPORTED);
3546 mgmt_pending_remove(cmd);
3547 goto failed;
3548 }
3549
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003550 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003551 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3552 MGMT_STATUS_REJECTED);
3553 mgmt_pending_remove(cmd);
3554 goto failed;
3555 }
3556
Andre Guedesc54c3862014-02-26 20:21:50 -03003557 /* If controller is scanning, it means the background scanning
3558 * is running. Thus, we should temporarily stop it in order to
3559 * set the discovery scanning parameters.
3560 */
3561 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3562 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003563
3564 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003565
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003566 /* All active scans will be done with either a resolvable
3567 * private address (when privacy feature has been enabled)
3568 * or unresolvable private address.
3569 */
3570 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003571 if (err < 0) {
3572 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3573 MGMT_STATUS_FAILED);
3574 mgmt_pending_remove(cmd);
3575 goto failed;
3576 }
3577
Andre Guedes7c307722013-04-30 15:29:28 -03003578 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003579 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3580 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003581 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003582 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3583 &param_cp);
3584
3585 memset(&enable_cp, 0, sizeof(enable_cp));
3586 enable_cp.enable = LE_SCAN_ENABLE;
3587 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3588 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3589 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003590 break;
3591
Andre Guedesf39799f2012-02-17 20:39:35 -03003592 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003593 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3594 MGMT_STATUS_INVALID_PARAMS);
3595 mgmt_pending_remove(cmd);
3596 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003597 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003598
Andre Guedes7c307722013-04-30 15:29:28 -03003599 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003600 if (err < 0)
3601 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003602 else
3603 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003604
3605failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003606 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003607 return err;
3608}
3609
Andre Guedes1183fdc2013-04-30 15:29:35 -03003610static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3611{
3612 struct pending_cmd *cmd;
3613 int err;
3614
3615 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3616 if (!cmd)
3617 return -ENOENT;
3618
3619 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3620 &hdev->discovery.type, sizeof(hdev->discovery.type));
3621 mgmt_pending_remove(cmd);
3622
3623 return err;
3624}
3625
Andre Guedes0e05bba2013-04-30 15:29:33 -03003626static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3627{
3628 BT_DBG("status %d", status);
3629
3630 hci_dev_lock(hdev);
3631
3632 if (status) {
3633 mgmt_stop_discovery_failed(hdev, status);
3634 goto unlock;
3635 }
3636
3637 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3638
3639unlock:
3640 hci_dev_unlock(hdev);
3641}
3642
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003643static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003644 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003645{
Johan Hedbergd9306502012-02-20 23:25:18 +02003646 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003647 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003648 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003649 int err;
3650
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003651 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003652
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003653 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003654
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003655 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003656 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003657 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3658 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003659 goto unlock;
3660 }
3661
3662 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003663 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3665 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003666 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003667 }
3668
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003669 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003670 if (!cmd) {
3671 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003672 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003673 }
3674
Andre Guedes0e05bba2013-04-30 15:29:33 -03003675 hci_req_init(&req, hdev);
3676
Johan Hedberg21a60d32014-06-10 14:05:58 +03003677 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003678
Johan Hedberg21a60d32014-06-10 14:05:58 +03003679 err = hci_req_run(&req, stop_discovery_complete);
3680 if (!err) {
3681 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003682 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003683 }
3684
Johan Hedberg21a60d32014-06-10 14:05:58 +03003685 mgmt_pending_remove(cmd);
3686
3687 /* If no HCI commands were sent we're done */
3688 if (err == -ENODATA) {
3689 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3690 &mgmt_cp->type, sizeof(mgmt_cp->type));
3691 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3692 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003693
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003694unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003695 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003696 return err;
3697}
3698
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003699static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003700 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003701{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003702 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003703 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003704 int err;
3705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003707
Johan Hedberg561aafb2012-01-04 13:31:59 +02003708 hci_dev_lock(hdev);
3709
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003710 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003711 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3712 MGMT_STATUS_FAILED, &cp->addr,
3713 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003714 goto failed;
3715 }
3716
Johan Hedberga198e7b2012-02-17 14:27:06 +02003717 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003718 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003719 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3720 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3721 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003722 goto failed;
3723 }
3724
3725 if (cp->name_known) {
3726 e->name_state = NAME_KNOWN;
3727 list_del(&e->list);
3728 } else {
3729 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003730 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003731 }
3732
Johan Hedberge3846622013-01-09 15:29:33 +02003733 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3734 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003735
3736failed:
3737 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003738 return err;
3739}
3740
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003741static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003742 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003743{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003744 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003745 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003746 int err;
3747
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003748 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003749
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003750 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003751 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3752 MGMT_STATUS_INVALID_PARAMS,
3753 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003754
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003755 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003756
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003757 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003758 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003759 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003760 else
Szymon Janca6785be2012-12-13 15:11:21 +01003761 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003762
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003763 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003764 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003765
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003766 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003767
3768 return err;
3769}
3770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003771static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003772 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003773{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003774 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003775 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003776 int err;
3777
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003778 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003779
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003780 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003781 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3782 MGMT_STATUS_INVALID_PARAMS,
3783 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003785 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003786
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003787 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003788 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003789 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003790 else
Szymon Janca6785be2012-12-13 15:11:21 +01003791 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003792
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003793 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003794 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003795
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003796 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003797
3798 return err;
3799}
3800
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003801static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3802 u16 len)
3803{
3804 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003805 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003806 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003807 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003808
3809 BT_DBG("%s", hdev->name);
3810
Szymon Jancc72d4b82012-03-16 16:02:57 +01003811 source = __le16_to_cpu(cp->source);
3812
3813 if (source > 0x0002)
3814 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3815 MGMT_STATUS_INVALID_PARAMS);
3816
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003817 hci_dev_lock(hdev);
3818
Szymon Jancc72d4b82012-03-16 16:02:57 +01003819 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003820 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3821 hdev->devid_product = __le16_to_cpu(cp->product);
3822 hdev->devid_version = __le16_to_cpu(cp->version);
3823
3824 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3825
Johan Hedberg890ea892013-03-15 17:06:52 -05003826 hci_req_init(&req, hdev);
3827 update_eir(&req);
3828 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003829
3830 hci_dev_unlock(hdev);
3831
3832 return err;
3833}
3834
Johan Hedberg4375f102013-09-25 13:26:10 +03003835static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3836{
3837 struct cmd_lookup match = { NULL, hdev };
3838
3839 if (status) {
3840 u8 mgmt_err = mgmt_status(status);
3841
3842 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3843 cmd_status_rsp, &mgmt_err);
3844 return;
3845 }
3846
3847 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3848 &match);
3849
3850 new_settings(hdev, match.sk);
3851
3852 if (match.sk)
3853 sock_put(match.sk);
3854}
3855
Marcel Holtmann21b51872013-10-10 09:47:53 -07003856static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3857 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003858{
3859 struct mgmt_mode *cp = data;
3860 struct pending_cmd *cmd;
3861 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003862 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003863 int err;
3864
3865 BT_DBG("request for %s", hdev->name);
3866
Johan Hedberge6fe7982013-10-02 15:45:22 +03003867 status = mgmt_le_support(hdev);
3868 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003869 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003870 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003871
3872 if (cp->val != 0x00 && cp->val != 0x01)
3873 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3874 MGMT_STATUS_INVALID_PARAMS);
3875
3876 hci_dev_lock(hdev);
3877
3878 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003879 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003880
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003881 /* The following conditions are ones which mean that we should
3882 * not do any HCI communication but directly send a mgmt
3883 * response to user space (after toggling the flag if
3884 * necessary).
3885 */
3886 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003887 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003888 bool changed = false;
3889
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003890 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3891 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003892 changed = true;
3893 }
3894
3895 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3896 if (err < 0)
3897 goto unlock;
3898
3899 if (changed)
3900 err = new_settings(hdev, sk);
3901
3902 goto unlock;
3903 }
3904
3905 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3906 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3907 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3908 MGMT_STATUS_BUSY);
3909 goto unlock;
3910 }
3911
3912 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3913 if (!cmd) {
3914 err = -ENOMEM;
3915 goto unlock;
3916 }
3917
3918 hci_req_init(&req, hdev);
3919
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003920 if (val)
3921 enable_advertising(&req);
3922 else
3923 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003924
3925 err = hci_req_run(&req, set_advertising_complete);
3926 if (err < 0)
3927 mgmt_pending_remove(cmd);
3928
3929unlock:
3930 hci_dev_unlock(hdev);
3931 return err;
3932}
3933
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003934static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3935 void *data, u16 len)
3936{
3937 struct mgmt_cp_set_static_address *cp = data;
3938 int err;
3939
3940 BT_DBG("%s", hdev->name);
3941
Marcel Holtmann62af4442013-10-02 22:10:32 -07003942 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003943 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003944 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003945
3946 if (hdev_is_powered(hdev))
3947 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3948 MGMT_STATUS_REJECTED);
3949
3950 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3951 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3952 return cmd_status(sk, hdev->id,
3953 MGMT_OP_SET_STATIC_ADDRESS,
3954 MGMT_STATUS_INVALID_PARAMS);
3955
3956 /* Two most significant bits shall be set */
3957 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3958 return cmd_status(sk, hdev->id,
3959 MGMT_OP_SET_STATIC_ADDRESS,
3960 MGMT_STATUS_INVALID_PARAMS);
3961 }
3962
3963 hci_dev_lock(hdev);
3964
3965 bacpy(&hdev->static_addr, &cp->bdaddr);
3966
3967 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3968
3969 hci_dev_unlock(hdev);
3970
3971 return err;
3972}
3973
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003974static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3975 void *data, u16 len)
3976{
3977 struct mgmt_cp_set_scan_params *cp = data;
3978 __u16 interval, window;
3979 int err;
3980
3981 BT_DBG("%s", hdev->name);
3982
3983 if (!lmp_le_capable(hdev))
3984 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3985 MGMT_STATUS_NOT_SUPPORTED);
3986
3987 interval = __le16_to_cpu(cp->interval);
3988
3989 if (interval < 0x0004 || interval > 0x4000)
3990 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3991 MGMT_STATUS_INVALID_PARAMS);
3992
3993 window = __le16_to_cpu(cp->window);
3994
3995 if (window < 0x0004 || window > 0x4000)
3996 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3997 MGMT_STATUS_INVALID_PARAMS);
3998
Marcel Holtmann899e1072013-10-14 09:55:32 -07003999 if (window > interval)
4000 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4001 MGMT_STATUS_INVALID_PARAMS);
4002
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004003 hci_dev_lock(hdev);
4004
4005 hdev->le_scan_interval = interval;
4006 hdev->le_scan_window = window;
4007
4008 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4009
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004010 /* If background scan is running, restart it so new parameters are
4011 * loaded.
4012 */
4013 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4014 hdev->discovery.state == DISCOVERY_STOPPED) {
4015 struct hci_request req;
4016
4017 hci_req_init(&req, hdev);
4018
4019 hci_req_add_le_scan_disable(&req);
4020 hci_req_add_le_passive_scan(&req);
4021
4022 hci_req_run(&req, NULL);
4023 }
4024
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004025 hci_dev_unlock(hdev);
4026
4027 return err;
4028}
4029
Johan Hedberg33e38b32013-03-15 17:07:05 -05004030static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4031{
4032 struct pending_cmd *cmd;
4033
4034 BT_DBG("status 0x%02x", status);
4035
4036 hci_dev_lock(hdev);
4037
4038 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4039 if (!cmd)
4040 goto unlock;
4041
4042 if (status) {
4043 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4044 mgmt_status(status));
4045 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004046 struct mgmt_mode *cp = cmd->param;
4047
4048 if (cp->val)
4049 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4050 else
4051 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4052
Johan Hedberg33e38b32013-03-15 17:07:05 -05004053 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4054 new_settings(hdev, cmd->sk);
4055 }
4056
4057 mgmt_pending_remove(cmd);
4058
4059unlock:
4060 hci_dev_unlock(hdev);
4061}
4062
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004063static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004064 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004065{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004066 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004067 struct pending_cmd *cmd;
4068 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004069 int err;
4070
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004071 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004072
Johan Hedberg56f87902013-10-02 13:43:13 +03004073 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4074 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004075 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4076 MGMT_STATUS_NOT_SUPPORTED);
4077
Johan Hedberga7e80f22013-01-09 16:05:19 +02004078 if (cp->val != 0x00 && cp->val != 0x01)
4079 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4080 MGMT_STATUS_INVALID_PARAMS);
4081
Johan Hedberg5400c042012-02-21 16:40:33 +02004082 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004083 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004084 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004085
4086 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004087 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004088 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004089
4090 hci_dev_lock(hdev);
4091
Johan Hedberg05cbf292013-03-15 17:07:07 -05004092 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4093 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4094 MGMT_STATUS_BUSY);
4095 goto unlock;
4096 }
4097
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004098 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4099 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4100 hdev);
4101 goto unlock;
4102 }
4103
Johan Hedberg33e38b32013-03-15 17:07:05 -05004104 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4105 data, len);
4106 if (!cmd) {
4107 err = -ENOMEM;
4108 goto unlock;
4109 }
4110
4111 hci_req_init(&req, hdev);
4112
Johan Hedberg406d7802013-03-15 17:07:09 -05004113 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004114
4115 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004116 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004117 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004118 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004119 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004120 }
4121
Johan Hedberg33e38b32013-03-15 17:07:05 -05004122unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004123 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004124
Antti Julkuf6422ec2011-06-22 13:11:56 +03004125 return err;
4126}
4127
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004128static void set_bredr_scan(struct hci_request *req)
4129{
4130 struct hci_dev *hdev = req->hdev;
4131 u8 scan = 0;
4132
4133 /* Ensure that fast connectable is disabled. This function will
4134 * not do anything if the page scan parameters are already what
4135 * they should be.
4136 */
4137 write_fast_connectable(req, false);
4138
4139 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4140 scan |= SCAN_PAGE;
4141 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4142 scan |= SCAN_INQUIRY;
4143
4144 if (scan)
4145 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4146}
4147
Johan Hedberg0663ca22013-10-02 13:43:14 +03004148static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4149{
4150 struct pending_cmd *cmd;
4151
4152 BT_DBG("status 0x%02x", status);
4153
4154 hci_dev_lock(hdev);
4155
4156 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4157 if (!cmd)
4158 goto unlock;
4159
4160 if (status) {
4161 u8 mgmt_err = mgmt_status(status);
4162
4163 /* We need to restore the flag if related HCI commands
4164 * failed.
4165 */
4166 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4167
4168 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4169 } else {
4170 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4171 new_settings(hdev, cmd->sk);
4172 }
4173
4174 mgmt_pending_remove(cmd);
4175
4176unlock:
4177 hci_dev_unlock(hdev);
4178}
4179
4180static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4181{
4182 struct mgmt_mode *cp = data;
4183 struct pending_cmd *cmd;
4184 struct hci_request req;
4185 int err;
4186
4187 BT_DBG("request for %s", hdev->name);
4188
4189 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4190 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4191 MGMT_STATUS_NOT_SUPPORTED);
4192
4193 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4194 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4195 MGMT_STATUS_REJECTED);
4196
4197 if (cp->val != 0x00 && cp->val != 0x01)
4198 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4199 MGMT_STATUS_INVALID_PARAMS);
4200
4201 hci_dev_lock(hdev);
4202
4203 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4204 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4205 goto unlock;
4206 }
4207
4208 if (!hdev_is_powered(hdev)) {
4209 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004210 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4211 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4212 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4213 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4214 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4215 }
4216
4217 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4218
4219 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4220 if (err < 0)
4221 goto unlock;
4222
4223 err = new_settings(hdev, sk);
4224 goto unlock;
4225 }
4226
4227 /* Reject disabling when powered on */
4228 if (!cp->val) {
4229 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4230 MGMT_STATUS_REJECTED);
4231 goto unlock;
4232 }
4233
4234 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4235 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4236 MGMT_STATUS_BUSY);
4237 goto unlock;
4238 }
4239
4240 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4241 if (!cmd) {
4242 err = -ENOMEM;
4243 goto unlock;
4244 }
4245
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004246 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004247 * generates the correct flags.
4248 */
4249 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4250
4251 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004252
4253 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4254 set_bredr_scan(&req);
4255
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004256 /* Since only the advertising data flags will change, there
4257 * is no need to update the scan response data.
4258 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004259 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004260
Johan Hedberg0663ca22013-10-02 13:43:14 +03004261 err = hci_req_run(&req, set_bredr_complete);
4262 if (err < 0)
4263 mgmt_pending_remove(cmd);
4264
4265unlock:
4266 hci_dev_unlock(hdev);
4267 return err;
4268}
4269
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004270static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4271 void *data, u16 len)
4272{
4273 struct mgmt_mode *cp = data;
4274 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004275 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004276 int err;
4277
4278 BT_DBG("request for %s", hdev->name);
4279
4280 status = mgmt_bredr_support(hdev);
4281 if (status)
4282 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4283 status);
4284
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004285 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004286 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004287 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4288 MGMT_STATUS_NOT_SUPPORTED);
4289
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004290 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004291 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4292 MGMT_STATUS_INVALID_PARAMS);
4293
4294 hci_dev_lock(hdev);
4295
4296 if (!hdev_is_powered(hdev)) {
4297 bool changed;
4298
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004299 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004300 changed = !test_and_set_bit(HCI_SC_ENABLED,
4301 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004302 if (cp->val == 0x02)
4303 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4304 else
4305 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4306 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004307 changed = test_and_clear_bit(HCI_SC_ENABLED,
4308 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004309 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4310 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004311
4312 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4313 if (err < 0)
4314 goto failed;
4315
4316 if (changed)
4317 err = new_settings(hdev, sk);
4318
4319 goto failed;
4320 }
4321
4322 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4323 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4324 MGMT_STATUS_BUSY);
4325 goto failed;
4326 }
4327
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004328 val = !!cp->val;
4329
4330 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4331 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004332 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4333 goto failed;
4334 }
4335
4336 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4337 if (!cmd) {
4338 err = -ENOMEM;
4339 goto failed;
4340 }
4341
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004342 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004343 if (err < 0) {
4344 mgmt_pending_remove(cmd);
4345 goto failed;
4346 }
4347
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004348 if (cp->val == 0x02)
4349 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4350 else
4351 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4352
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004353failed:
4354 hci_dev_unlock(hdev);
4355 return err;
4356}
4357
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004358static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4359 void *data, u16 len)
4360{
4361 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004362 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004363 int err;
4364
4365 BT_DBG("request for %s", hdev->name);
4366
Johan Hedbergb97109792014-06-24 14:00:28 +03004367 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004368 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4369 MGMT_STATUS_INVALID_PARAMS);
4370
4371 hci_dev_lock(hdev);
4372
4373 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004374 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4375 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004376 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004377 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4378 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004379
Johan Hedbergb97109792014-06-24 14:00:28 +03004380 if (cp->val == 0x02)
4381 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4382 &hdev->dev_flags);
4383 else
4384 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4385 &hdev->dev_flags);
4386
4387 if (hdev_is_powered(hdev) && use_changed &&
4388 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4389 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4390 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4391 sizeof(mode), &mode);
4392 }
4393
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004394 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4395 if (err < 0)
4396 goto unlock;
4397
4398 if (changed)
4399 err = new_settings(hdev, sk);
4400
4401unlock:
4402 hci_dev_unlock(hdev);
4403 return err;
4404}
4405
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004406static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4407 u16 len)
4408{
4409 struct mgmt_cp_set_privacy *cp = cp_data;
4410 bool changed;
4411 int err;
4412
4413 BT_DBG("request for %s", hdev->name);
4414
4415 if (!lmp_le_capable(hdev))
4416 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4417 MGMT_STATUS_NOT_SUPPORTED);
4418
4419 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4420 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4421 MGMT_STATUS_INVALID_PARAMS);
4422
4423 if (hdev_is_powered(hdev))
4424 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4425 MGMT_STATUS_REJECTED);
4426
4427 hci_dev_lock(hdev);
4428
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004429 /* If user space supports this command it is also expected to
4430 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4431 */
4432 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4433
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004434 if (cp->privacy) {
4435 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4436 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4437 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4438 } else {
4439 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4440 memset(hdev->irk, 0, sizeof(hdev->irk));
4441 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4442 }
4443
4444 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4445 if (err < 0)
4446 goto unlock;
4447
4448 if (changed)
4449 err = new_settings(hdev, sk);
4450
4451unlock:
4452 hci_dev_unlock(hdev);
4453 return err;
4454}
4455
Johan Hedberg41edf162014-02-18 10:19:35 +02004456static bool irk_is_valid(struct mgmt_irk_info *irk)
4457{
4458 switch (irk->addr.type) {
4459 case BDADDR_LE_PUBLIC:
4460 return true;
4461
4462 case BDADDR_LE_RANDOM:
4463 /* Two most significant bits shall be set */
4464 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4465 return false;
4466 return true;
4467 }
4468
4469 return false;
4470}
4471
4472static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4473 u16 len)
4474{
4475 struct mgmt_cp_load_irks *cp = cp_data;
4476 u16 irk_count, expected_len;
4477 int i, err;
4478
4479 BT_DBG("request for %s", hdev->name);
4480
4481 if (!lmp_le_capable(hdev))
4482 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4483 MGMT_STATUS_NOT_SUPPORTED);
4484
4485 irk_count = __le16_to_cpu(cp->irk_count);
4486
4487 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4488 if (expected_len != len) {
4489 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004490 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004491 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4492 MGMT_STATUS_INVALID_PARAMS);
4493 }
4494
4495 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4496
4497 for (i = 0; i < irk_count; i++) {
4498 struct mgmt_irk_info *key = &cp->irks[i];
4499
4500 if (!irk_is_valid(key))
4501 return cmd_status(sk, hdev->id,
4502 MGMT_OP_LOAD_IRKS,
4503 MGMT_STATUS_INVALID_PARAMS);
4504 }
4505
4506 hci_dev_lock(hdev);
4507
4508 hci_smp_irks_clear(hdev);
4509
4510 for (i = 0; i < irk_count; i++) {
4511 struct mgmt_irk_info *irk = &cp->irks[i];
4512 u8 addr_type;
4513
4514 if (irk->addr.type == BDADDR_LE_PUBLIC)
4515 addr_type = ADDR_LE_DEV_PUBLIC;
4516 else
4517 addr_type = ADDR_LE_DEV_RANDOM;
4518
4519 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4520 BDADDR_ANY);
4521 }
4522
4523 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4524
4525 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4526
4527 hci_dev_unlock(hdev);
4528
4529 return err;
4530}
4531
Johan Hedberg3f706b72013-01-20 14:27:16 +02004532static bool ltk_is_valid(struct mgmt_ltk_info *key)
4533{
4534 if (key->master != 0x00 && key->master != 0x01)
4535 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004536
4537 switch (key->addr.type) {
4538 case BDADDR_LE_PUBLIC:
4539 return true;
4540
4541 case BDADDR_LE_RANDOM:
4542 /* Two most significant bits shall be set */
4543 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4544 return false;
4545 return true;
4546 }
4547
4548 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004549}
4550
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004551static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004552 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004553{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004554 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4555 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004556 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004557
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004558 BT_DBG("request for %s", hdev->name);
4559
4560 if (!lmp_le_capable(hdev))
4561 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4562 MGMT_STATUS_NOT_SUPPORTED);
4563
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004564 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004565
4566 expected_len = sizeof(*cp) + key_count *
4567 sizeof(struct mgmt_ltk_info);
4568 if (expected_len != len) {
4569 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004570 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004571 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004572 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004573 }
4574
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004575 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004576
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004577 for (i = 0; i < key_count; i++) {
4578 struct mgmt_ltk_info *key = &cp->keys[i];
4579
Johan Hedberg3f706b72013-01-20 14:27:16 +02004580 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004581 return cmd_status(sk, hdev->id,
4582 MGMT_OP_LOAD_LONG_TERM_KEYS,
4583 MGMT_STATUS_INVALID_PARAMS);
4584 }
4585
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004586 hci_dev_lock(hdev);
4587
4588 hci_smp_ltks_clear(hdev);
4589
4590 for (i = 0; i < key_count; i++) {
4591 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004592 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004593
4594 if (key->addr.type == BDADDR_LE_PUBLIC)
4595 addr_type = ADDR_LE_DEV_PUBLIC;
4596 else
4597 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004598
4599 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004600 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004601 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004602 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004603
Johan Hedberg61b43352014-05-29 19:36:53 +03004604 switch (key->type) {
4605 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004606 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004607 break;
4608 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004609 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004610 break;
4611 default:
4612 continue;
4613 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004614
Johan Hedberg35d70272014-02-19 14:57:47 +02004615 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004616 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004617 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004618 }
4619
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004620 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4621 NULL, 0);
4622
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004623 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004624
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004625 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004626}
4627
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004628struct cmd_conn_lookup {
4629 struct hci_conn *conn;
4630 bool valid_tx_power;
4631 u8 mgmt_status;
4632};
4633
4634static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4635{
4636 struct cmd_conn_lookup *match = data;
4637 struct mgmt_cp_get_conn_info *cp;
4638 struct mgmt_rp_get_conn_info rp;
4639 struct hci_conn *conn = cmd->user_data;
4640
4641 if (conn != match->conn)
4642 return;
4643
4644 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4645
4646 memset(&rp, 0, sizeof(rp));
4647 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4648 rp.addr.type = cp->addr.type;
4649
4650 if (!match->mgmt_status) {
4651 rp.rssi = conn->rssi;
4652
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004653 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004654 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004655 rp.max_tx_power = conn->max_tx_power;
4656 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004657 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004658 rp.max_tx_power = HCI_TX_POWER_INVALID;
4659 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004660 }
4661
4662 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4663 match->mgmt_status, &rp, sizeof(rp));
4664
4665 hci_conn_drop(conn);
4666
4667 mgmt_pending_remove(cmd);
4668}
4669
4670static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4671{
4672 struct hci_cp_read_rssi *cp;
4673 struct hci_conn *conn;
4674 struct cmd_conn_lookup match;
4675 u16 handle;
4676
4677 BT_DBG("status 0x%02x", status);
4678
4679 hci_dev_lock(hdev);
4680
4681 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004682 * otherwise we assume it's not valid. At the moment we assume that
4683 * either both or none of current and max values are valid to keep code
4684 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004685 */
4686 match.valid_tx_power = !status;
4687
4688 /* Commands sent in request are either Read RSSI or Read Transmit Power
4689 * Level so we check which one was last sent to retrieve connection
4690 * handle. Both commands have handle as first parameter so it's safe to
4691 * cast data on the same command struct.
4692 *
4693 * First command sent is always Read RSSI and we fail only if it fails.
4694 * In other case we simply override error to indicate success as we
4695 * already remembered if TX power value is actually valid.
4696 */
4697 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4698 if (!cp) {
4699 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4700 status = 0;
4701 }
4702
4703 if (!cp) {
4704 BT_ERR("invalid sent_cmd in response");
4705 goto unlock;
4706 }
4707
4708 handle = __le16_to_cpu(cp->handle);
4709 conn = hci_conn_hash_lookup_handle(hdev, handle);
4710 if (!conn) {
4711 BT_ERR("unknown handle (%d) in response", handle);
4712 goto unlock;
4713 }
4714
4715 match.conn = conn;
4716 match.mgmt_status = mgmt_status(status);
4717
4718 /* Cache refresh is complete, now reply for mgmt request for given
4719 * connection only.
4720 */
4721 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4722 get_conn_info_complete, &match);
4723
4724unlock:
4725 hci_dev_unlock(hdev);
4726}
4727
4728static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4729 u16 len)
4730{
4731 struct mgmt_cp_get_conn_info *cp = data;
4732 struct mgmt_rp_get_conn_info rp;
4733 struct hci_conn *conn;
4734 unsigned long conn_info_age;
4735 int err = 0;
4736
4737 BT_DBG("%s", hdev->name);
4738
4739 memset(&rp, 0, sizeof(rp));
4740 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4741 rp.addr.type = cp->addr.type;
4742
4743 if (!bdaddr_type_is_valid(cp->addr.type))
4744 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4745 MGMT_STATUS_INVALID_PARAMS,
4746 &rp, sizeof(rp));
4747
4748 hci_dev_lock(hdev);
4749
4750 if (!hdev_is_powered(hdev)) {
4751 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4753 goto unlock;
4754 }
4755
4756 if (cp->addr.type == BDADDR_BREDR)
4757 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4758 &cp->addr.bdaddr);
4759 else
4760 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4761
4762 if (!conn || conn->state != BT_CONNECTED) {
4763 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4764 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4765 goto unlock;
4766 }
4767
4768 /* To avoid client trying to guess when to poll again for information we
4769 * calculate conn info age as random value between min/max set in hdev.
4770 */
4771 conn_info_age = hdev->conn_info_min_age +
4772 prandom_u32_max(hdev->conn_info_max_age -
4773 hdev->conn_info_min_age);
4774
4775 /* Query controller to refresh cached values if they are too old or were
4776 * never read.
4777 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004778 if (time_after(jiffies, conn->conn_info_timestamp +
4779 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004780 !conn->conn_info_timestamp) {
4781 struct hci_request req;
4782 struct hci_cp_read_tx_power req_txp_cp;
4783 struct hci_cp_read_rssi req_rssi_cp;
4784 struct pending_cmd *cmd;
4785
4786 hci_req_init(&req, hdev);
4787 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4788 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4789 &req_rssi_cp);
4790
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004791 /* For LE links TX power does not change thus we don't need to
4792 * query for it once value is known.
4793 */
4794 if (!bdaddr_type_is_le(cp->addr.type) ||
4795 conn->tx_power == HCI_TX_POWER_INVALID) {
4796 req_txp_cp.handle = cpu_to_le16(conn->handle);
4797 req_txp_cp.type = 0x00;
4798 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4799 sizeof(req_txp_cp), &req_txp_cp);
4800 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004801
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004802 /* Max TX power needs to be read only once per connection */
4803 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4804 req_txp_cp.handle = cpu_to_le16(conn->handle);
4805 req_txp_cp.type = 0x01;
4806 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4807 sizeof(req_txp_cp), &req_txp_cp);
4808 }
4809
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004810 err = hci_req_run(&req, conn_info_refresh_complete);
4811 if (err < 0)
4812 goto unlock;
4813
4814 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4815 data, len);
4816 if (!cmd) {
4817 err = -ENOMEM;
4818 goto unlock;
4819 }
4820
4821 hci_conn_hold(conn);
4822 cmd->user_data = conn;
4823
4824 conn->conn_info_timestamp = jiffies;
4825 } else {
4826 /* Cache is valid, just reply with values cached in hci_conn */
4827 rp.rssi = conn->rssi;
4828 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004829 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004830
4831 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4832 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4833 }
4834
4835unlock:
4836 hci_dev_unlock(hdev);
4837 return err;
4838}
4839
Johan Hedberg95868422014-06-28 17:54:07 +03004840static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4841{
4842 struct mgmt_cp_get_clock_info *cp;
4843 struct mgmt_rp_get_clock_info rp;
4844 struct hci_cp_read_clock *hci_cp;
4845 struct pending_cmd *cmd;
4846 struct hci_conn *conn;
4847
4848 BT_DBG("%s status %u", hdev->name, status);
4849
4850 hci_dev_lock(hdev);
4851
4852 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4853 if (!hci_cp)
4854 goto unlock;
4855
4856 if (hci_cp->which) {
4857 u16 handle = __le16_to_cpu(hci_cp->handle);
4858 conn = hci_conn_hash_lookup_handle(hdev, handle);
4859 } else {
4860 conn = NULL;
4861 }
4862
4863 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4864 if (!cmd)
4865 goto unlock;
4866
4867 cp = cmd->param;
4868
4869 memset(&rp, 0, sizeof(rp));
4870 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4871
4872 if (status)
4873 goto send_rsp;
4874
4875 rp.local_clock = cpu_to_le32(hdev->clock);
4876
4877 if (conn) {
4878 rp.piconet_clock = cpu_to_le32(conn->clock);
4879 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4880 }
4881
4882send_rsp:
4883 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4884 &rp, sizeof(rp));
4885 mgmt_pending_remove(cmd);
4886 if (conn)
4887 hci_conn_drop(conn);
4888
4889unlock:
4890 hci_dev_unlock(hdev);
4891}
4892
4893static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4894 u16 len)
4895{
4896 struct mgmt_cp_get_clock_info *cp = data;
4897 struct mgmt_rp_get_clock_info rp;
4898 struct hci_cp_read_clock hci_cp;
4899 struct pending_cmd *cmd;
4900 struct hci_request req;
4901 struct hci_conn *conn;
4902 int err;
4903
4904 BT_DBG("%s", hdev->name);
4905
4906 memset(&rp, 0, sizeof(rp));
4907 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4908 rp.addr.type = cp->addr.type;
4909
4910 if (cp->addr.type != BDADDR_BREDR)
4911 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4912 MGMT_STATUS_INVALID_PARAMS,
4913 &rp, sizeof(rp));
4914
4915 hci_dev_lock(hdev);
4916
4917 if (!hdev_is_powered(hdev)) {
4918 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4919 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4920 goto unlock;
4921 }
4922
4923 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4924 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4925 &cp->addr.bdaddr);
4926 if (!conn || conn->state != BT_CONNECTED) {
4927 err = cmd_complete(sk, hdev->id,
4928 MGMT_OP_GET_CLOCK_INFO,
4929 MGMT_STATUS_NOT_CONNECTED,
4930 &rp, sizeof(rp));
4931 goto unlock;
4932 }
4933 } else {
4934 conn = NULL;
4935 }
4936
4937 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4938 if (!cmd) {
4939 err = -ENOMEM;
4940 goto unlock;
4941 }
4942
4943 hci_req_init(&req, hdev);
4944
4945 memset(&hci_cp, 0, sizeof(hci_cp));
4946 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4947
4948 if (conn) {
4949 hci_conn_hold(conn);
4950 cmd->user_data = conn;
4951
4952 hci_cp.handle = cpu_to_le16(conn->handle);
4953 hci_cp.which = 0x01; /* Piconet clock */
4954 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4955 }
4956
4957 err = hci_req_run(&req, get_clock_info_complete);
4958 if (err < 0)
4959 mgmt_pending_remove(cmd);
4960
4961unlock:
4962 hci_dev_unlock(hdev);
4963 return err;
4964}
4965
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004966static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004967 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4968 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004969 bool var_len;
4970 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004971} mgmt_handlers[] = {
4972 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004973 { read_version, false, MGMT_READ_VERSION_SIZE },
4974 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4975 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4976 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4977 { set_powered, false, MGMT_SETTING_SIZE },
4978 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4979 { set_connectable, false, MGMT_SETTING_SIZE },
4980 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4981 { set_pairable, false, MGMT_SETTING_SIZE },
4982 { set_link_security, false, MGMT_SETTING_SIZE },
4983 { set_ssp, false, MGMT_SETTING_SIZE },
4984 { set_hs, false, MGMT_SETTING_SIZE },
4985 { set_le, false, MGMT_SETTING_SIZE },
4986 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4987 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4988 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4989 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4990 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4991 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4992 { disconnect, false, MGMT_DISCONNECT_SIZE },
4993 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4994 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4995 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4996 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4997 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4998 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4999 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5000 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5001 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5002 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5003 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5004 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005005 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005006 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5007 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5008 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5009 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5010 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5011 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005012 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005013 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005014 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005015 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005016 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005017 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005018 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005019 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005020 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005021 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005022 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005023};
5024
5025
Johan Hedberg03811012010-12-08 00:21:06 +02005026int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5027{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005028 void *buf;
5029 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005030 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005031 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005032 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005033 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005034 int err;
5035
5036 BT_DBG("got %zu bytes", msglen);
5037
5038 if (msglen < sizeof(*hdr))
5039 return -EINVAL;
5040
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005041 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005042 if (!buf)
5043 return -ENOMEM;
5044
5045 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5046 err = -EFAULT;
5047 goto done;
5048 }
5049
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005050 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005051 opcode = __le16_to_cpu(hdr->opcode);
5052 index = __le16_to_cpu(hdr->index);
5053 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005054
5055 if (len != msglen - sizeof(*hdr)) {
5056 err = -EINVAL;
5057 goto done;
5058 }
5059
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005060 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005061 hdev = hci_dev_get(index);
5062 if (!hdev) {
5063 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005064 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005065 goto done;
5066 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005067
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005068 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
5069 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005070 err = cmd_status(sk, index, opcode,
5071 MGMT_STATUS_INVALID_INDEX);
5072 goto done;
5073 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005074 }
5075
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005076 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005077 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005078 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005079 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005080 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005081 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005082 }
5083
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005084 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005085 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005086 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005087 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005088 goto done;
5089 }
5090
Johan Hedbergbe22b542012-03-01 22:24:41 +02005091 handler = &mgmt_handlers[opcode];
5092
5093 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005094 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005095 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005096 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005097 goto done;
5098 }
5099
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005100 if (hdev)
5101 mgmt_init_hdev(sk, hdev);
5102
5103 cp = buf + sizeof(*hdr);
5104
Johan Hedbergbe22b542012-03-01 22:24:41 +02005105 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005106 if (err < 0)
5107 goto done;
5108
Johan Hedberg03811012010-12-08 00:21:06 +02005109 err = msglen;
5110
5111done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005112 if (hdev)
5113 hci_dev_put(hdev);
5114
Johan Hedberg03811012010-12-08 00:21:06 +02005115 kfree(buf);
5116 return err;
5117}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005118
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005119void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005120{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005121 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005122 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005123
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005124 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005125}
5126
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005127void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005128{
Johan Hedberg5f159032012-03-02 03:13:19 +02005129 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005130
Marcel Holtmann1514b892013-10-06 08:25:01 -07005131 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005132 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005133
Johan Hedberg744cf192011-11-08 20:40:14 +02005134 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005135
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005136 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005137}
5138
Andre Guedes6046dc32014-02-26 20:21:51 -03005139/* This function requires the caller holds hdev->lock */
5140static void restart_le_auto_conns(struct hci_dev *hdev)
5141{
5142 struct hci_conn_params *p;
5143
5144 list_for_each_entry(p, &hdev->le_conn_params, list) {
5145 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
5146 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
5147 }
5148}
5149
Johan Hedberg229ab392013-03-15 17:06:53 -05005150static void powered_complete(struct hci_dev *hdev, u8 status)
5151{
5152 struct cmd_lookup match = { NULL, hdev };
5153
5154 BT_DBG("status 0x%02x", status);
5155
5156 hci_dev_lock(hdev);
5157
Andre Guedes6046dc32014-02-26 20:21:51 -03005158 restart_le_auto_conns(hdev);
5159
Johan Hedberg229ab392013-03-15 17:06:53 -05005160 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5161
5162 new_settings(hdev, match.sk);
5163
5164 hci_dev_unlock(hdev);
5165
5166 if (match.sk)
5167 sock_put(match.sk);
5168}
5169
Johan Hedberg70da6242013-03-15 17:06:51 -05005170static int powered_update_hci(struct hci_dev *hdev)
5171{
Johan Hedberg890ea892013-03-15 17:06:52 -05005172 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005173 u8 link_sec;
5174
Johan Hedberg890ea892013-03-15 17:06:52 -05005175 hci_req_init(&req, hdev);
5176
Johan Hedberg70da6242013-03-15 17:06:51 -05005177 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5178 !lmp_host_ssp_capable(hdev)) {
5179 u8 ssp = 1;
5180
Johan Hedberg890ea892013-03-15 17:06:52 -05005181 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005182 }
5183
Johan Hedbergc73eee92013-04-19 18:35:21 +03005184 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5185 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005186 struct hci_cp_write_le_host_supported cp;
5187
5188 cp.le = 1;
5189 cp.simul = lmp_le_br_capable(hdev);
5190
5191 /* Check first if we already have the right
5192 * host state (host features set)
5193 */
5194 if (cp.le != lmp_host_le_capable(hdev) ||
5195 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005196 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5197 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005198 }
5199
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005200 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005201 /* Make sure the controller has a good default for
5202 * advertising data. This also applies to the case
5203 * where BR/EDR was toggled during the AUTO_OFF phase.
5204 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005205 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005206 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005207 update_scan_rsp_data(&req);
5208 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005209
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005210 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5211 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005212 }
5213
Johan Hedberg70da6242013-03-15 17:06:51 -05005214 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5215 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005216 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5217 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005218
5219 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005220 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5221 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005222 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005223 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005224 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005225 }
5226
Johan Hedberg229ab392013-03-15 17:06:53 -05005227 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005228}
5229
Johan Hedberg744cf192011-11-08 20:40:14 +02005230int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005231{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005232 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005233 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5234 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005235 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005236
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005237 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5238 return 0;
5239
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005240 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005241 if (powered_update_hci(hdev) == 0)
5242 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005243
Johan Hedberg229ab392013-03-15 17:06:53 -05005244 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5245 &match);
5246 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005247 }
5248
Johan Hedberg229ab392013-03-15 17:06:53 -05005249 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5250 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5251
5252 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5253 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5254 zero_cod, sizeof(zero_cod), NULL);
5255
5256new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005257 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005258
5259 if (match.sk)
5260 sock_put(match.sk);
5261
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005262 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005263}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005264
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005265void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005266{
5267 struct pending_cmd *cmd;
5268 u8 status;
5269
5270 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5271 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005272 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005273
5274 if (err == -ERFKILL)
5275 status = MGMT_STATUS_RFKILLED;
5276 else
5277 status = MGMT_STATUS_FAILED;
5278
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005279 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005280
5281 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005282}
5283
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005284void mgmt_discoverable_timeout(struct hci_dev *hdev)
5285{
5286 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005287
5288 hci_dev_lock(hdev);
5289
5290 /* When discoverable timeout triggers, then just make sure
5291 * the limited discoverable flag is cleared. Even in the case
5292 * of a timeout triggered from general discoverable, it is
5293 * safe to unconditionally clear the flag.
5294 */
5295 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005296 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005297
5298 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005299 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5300 u8 scan = SCAN_PAGE;
5301 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5302 sizeof(scan), &scan);
5303 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005304 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005305 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005306 hci_req_run(&req, NULL);
5307
5308 hdev->discov_timeout = 0;
5309
Johan Hedberg9a43e252013-10-20 19:00:07 +03005310 new_settings(hdev, NULL);
5311
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005312 hci_dev_unlock(hdev);
5313}
5314
Marcel Holtmann86a75642013-10-15 06:33:54 -07005315void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005316{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005317 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005318
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005319 /* Nothing needed here if there's a pending command since that
5320 * commands request completion callback takes care of everything
5321 * necessary.
5322 */
5323 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005324 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005325
Johan Hedbergbd107992014-02-24 14:52:19 +02005326 /* Powering off may clear the scan mode - don't let that interfere */
5327 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5328 return;
5329
Johan Hedberg9a43e252013-10-20 19:00:07 +03005330 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005331 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005332 } else {
5333 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005334 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005335 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005336
Johan Hedberg9a43e252013-10-20 19:00:07 +03005337 if (changed) {
5338 struct hci_request req;
5339
5340 /* In case this change in discoverable was triggered by
5341 * a disabling of connectable there could be a need to
5342 * update the advertising flags.
5343 */
5344 hci_req_init(&req, hdev);
5345 update_adv_data(&req);
5346 hci_req_run(&req, NULL);
5347
Marcel Holtmann86a75642013-10-15 06:33:54 -07005348 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005349 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005350}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005351
Marcel Holtmanna3309162013-10-15 06:33:55 -07005352void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005353{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005354 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005355
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005356 /* Nothing needed here if there's a pending command since that
5357 * commands request completion callback takes care of everything
5358 * necessary.
5359 */
5360 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005361 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005362
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005363 /* Powering off may clear the scan mode - don't let that interfere */
5364 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5365 return;
5366
Marcel Holtmanna3309162013-10-15 06:33:55 -07005367 if (connectable)
5368 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5369 else
5370 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005371
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005372 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005373 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005374}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005375
Johan Hedberg778b2352014-02-24 14:52:17 +02005376void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5377{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005378 /* Powering off may stop advertising - don't let that interfere */
5379 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5380 return;
5381
Johan Hedberg778b2352014-02-24 14:52:17 +02005382 if (advertising)
5383 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5384 else
5385 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5386}
5387
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005388void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005389{
Johan Hedbergca69b792011-11-11 18:10:00 +02005390 u8 mgmt_err = mgmt_status(status);
5391
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005392 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005393 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005394 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005395
5396 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005397 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005398 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005399}
5400
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005401void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5402 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005403{
Johan Hedberg86742e12011-11-07 23:13:38 +02005404 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005405
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005406 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005407
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005408 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005409 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005410 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005411 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005412 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005413 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005414
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005415 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005416}
Johan Hedbergf7520542011-01-20 12:34:39 +02005417
Johan Hedbergd7b25452014-05-23 13:19:53 +03005418static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5419{
5420 if (ltk->authenticated)
5421 return MGMT_LTK_AUTHENTICATED;
5422
5423 return MGMT_LTK_UNAUTHENTICATED;
5424}
5425
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005426void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005427{
5428 struct mgmt_ev_new_long_term_key ev;
5429
5430 memset(&ev, 0, sizeof(ev));
5431
Marcel Holtmann5192d302014-02-19 17:11:58 -08005432 /* Devices using resolvable or non-resolvable random addresses
5433 * without providing an indentity resolving key don't require
5434 * to store long term keys. Their addresses will change the
5435 * next time around.
5436 *
5437 * Only when a remote device provides an identity address
5438 * make sure the long term key is stored. If the remote
5439 * identity is known, the long term keys are internally
5440 * mapped to the identity address. So allow static random
5441 * and public addresses here.
5442 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005443 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5444 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5445 ev.store_hint = 0x00;
5446 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005447 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005448
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005449 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005450 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005451 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005452 ev.key.enc_size = key->enc_size;
5453 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005454 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005455
Johan Hedberg2ceba532014-06-16 19:25:16 +03005456 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005457 ev.key.master = 1;
5458
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005459 memcpy(ev.key.val, key->val, sizeof(key->val));
5460
Marcel Holtmann083368f2013-10-15 14:26:29 -07005461 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005462}
5463
Johan Hedberg95fbac82014-02-19 15:18:31 +02005464void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5465{
5466 struct mgmt_ev_new_irk ev;
5467
5468 memset(&ev, 0, sizeof(ev));
5469
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005470 /* For identity resolving keys from devices that are already
5471 * using a public address or static random address, do not
5472 * ask for storing this key. The identity resolving key really
5473 * is only mandatory for devices using resovlable random
5474 * addresses.
5475 *
5476 * Storing all identity resolving keys has the downside that
5477 * they will be also loaded on next boot of they system. More
5478 * identity resolving keys, means more time during scanning is
5479 * needed to actually resolve these addresses.
5480 */
5481 if (bacmp(&irk->rpa, BDADDR_ANY))
5482 ev.store_hint = 0x01;
5483 else
5484 ev.store_hint = 0x00;
5485
Johan Hedberg95fbac82014-02-19 15:18:31 +02005486 bacpy(&ev.rpa, &irk->rpa);
5487 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5488 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5489 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5490
5491 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5492}
5493
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005494void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5495 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005496{
5497 struct mgmt_ev_new_csrk ev;
5498
5499 memset(&ev, 0, sizeof(ev));
5500
5501 /* Devices using resolvable or non-resolvable random addresses
5502 * without providing an indentity resolving key don't require
5503 * to store signature resolving keys. Their addresses will change
5504 * the next time around.
5505 *
5506 * Only when a remote device provides an identity address
5507 * make sure the signature resolving key is stored. So allow
5508 * static random and public addresses here.
5509 */
5510 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5511 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5512 ev.store_hint = 0x00;
5513 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005514 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005515
5516 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5517 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5518 ev.key.master = csrk->master;
5519 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5520
5521 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5522}
5523
Marcel Holtmann94933992013-10-15 10:26:39 -07005524static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5525 u8 data_len)
5526{
5527 eir[eir_len++] = sizeof(type) + data_len;
5528 eir[eir_len++] = type;
5529 memcpy(&eir[eir_len], data, data_len);
5530 eir_len += data_len;
5531
5532 return eir_len;
5533}
5534
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005535void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5536 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5537 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005538{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005539 char buf[512];
5540 struct mgmt_ev_device_connected *ev = (void *) buf;
5541 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005542
Johan Hedbergb644ba32012-01-17 21:48:47 +02005543 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005544 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005545
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005546 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005547
Johan Hedbergb644ba32012-01-17 21:48:47 +02005548 if (name_len > 0)
5549 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005550 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005551
5552 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005553 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005554 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005555
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005556 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005557
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005558 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5559 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005560}
5561
Johan Hedberg8962ee72011-01-20 12:40:27 +02005562static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5563{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005564 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005565 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005566 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005567
Johan Hedberg88c3df12012-02-09 14:27:38 +02005568 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5569 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005570
Johan Hedbergaee9b212012-02-18 15:07:59 +02005571 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005572 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005573
5574 *sk = cmd->sk;
5575 sock_hold(*sk);
5576
Johan Hedberga664b5b2011-02-19 12:06:02 -03005577 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005578}
5579
Johan Hedberg124f6e32012-02-09 13:50:12 +02005580static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005581{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005582 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005583 struct mgmt_cp_unpair_device *cp = cmd->param;
5584 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005585
5586 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005587 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5588 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005589
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005590 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5591
Johan Hedbergaee9b212012-02-18 15:07:59 +02005592 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005593
5594 mgmt_pending_remove(cmd);
5595}
5596
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005597void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005598 u8 link_type, u8 addr_type, u8 reason,
5599 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005600{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005601 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005602 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005603 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005604
Johan Hedberg8b064a32014-02-24 14:52:22 +02005605 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5606 if (power_off) {
5607 struct mgmt_mode *cp = power_off->param;
5608
5609 /* The connection is still in hci_conn_hash so test for 1
5610 * instead of 0 to know if this is the last one.
5611 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005612 if (!cp->val && hci_conn_count(hdev) == 1) {
5613 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005614 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005615 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005616 }
5617
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005618 if (!mgmt_connected)
5619 return;
5620
Andre Guedes57eb7762013-10-30 19:01:41 -03005621 if (link_type != ACL_LINK && link_type != LE_LINK)
5622 return;
5623
Johan Hedberg744cf192011-11-08 20:40:14 +02005624 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005625
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005626 bacpy(&ev.addr.bdaddr, bdaddr);
5627 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5628 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005629
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005630 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005631
5632 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005633 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005634
Johan Hedberg124f6e32012-02-09 13:50:12 +02005635 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005636 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005637}
5638
Marcel Holtmann78929242013-10-06 23:55:47 -07005639void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5640 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005641{
Andre Guedes3655bba2013-10-30 19:01:40 -03005642 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5643 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005644 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005645 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005646
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005647 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5648 hdev);
5649
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005650 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005651 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005652 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005653
Andre Guedes3655bba2013-10-30 19:01:40 -03005654 cp = cmd->param;
5655
5656 if (bacmp(bdaddr, &cp->addr.bdaddr))
5657 return;
5658
5659 if (cp->addr.type != bdaddr_type)
5660 return;
5661
Johan Hedberg88c3df12012-02-09 14:27:38 +02005662 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005663 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005664
Marcel Holtmann78929242013-10-06 23:55:47 -07005665 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5666 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005667
Johan Hedberga664b5b2011-02-19 12:06:02 -03005668 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005669}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005670
Marcel Holtmann445608d2013-10-06 23:55:48 -07005671void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5672 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005673{
5674 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005675 struct pending_cmd *power_off;
5676
5677 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5678 if (power_off) {
5679 struct mgmt_mode *cp = power_off->param;
5680
5681 /* The connection is still in hci_conn_hash so test for 1
5682 * instead of 0 to know if this is the last one.
5683 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005684 if (!cp->val && hci_conn_count(hdev) == 1) {
5685 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005686 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005687 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005688 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005689
Johan Hedberg4c659c32011-11-07 23:13:39 +02005690 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005691 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005692 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005693
Marcel Holtmann445608d2013-10-06 23:55:48 -07005694 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005695}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005696
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005697void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005698{
5699 struct mgmt_ev_pin_code_request ev;
5700
Johan Hedbergd8457692012-02-17 14:24:57 +02005701 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005702 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005703 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005704
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005705 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005706}
5707
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005708void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5709 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005710{
5711 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005712 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005713
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005714 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005715 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005716 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005717
Johan Hedbergd8457692012-02-17 14:24:57 +02005718 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005719 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005720
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005721 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5722 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005723
Johan Hedberga664b5b2011-02-19 12:06:02 -03005724 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005725}
5726
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005727void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5728 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005729{
5730 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005731 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005732
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005733 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005734 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005735 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005736
Johan Hedbergd8457692012-02-17 14:24:57 +02005737 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005738 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005739
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005740 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5741 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005742
Johan Hedberga664b5b2011-02-19 12:06:02 -03005743 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005744}
Johan Hedberga5c29682011-02-19 12:05:57 -03005745
Johan Hedberg744cf192011-11-08 20:40:14 +02005746int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005747 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005748 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005749{
5750 struct mgmt_ev_user_confirm_request ev;
5751
Johan Hedberg744cf192011-11-08 20:40:14 +02005752 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005753
Johan Hedberg272d90d2012-02-09 15:26:12 +02005754 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005755 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005756 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005757 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005758
Johan Hedberg744cf192011-11-08 20:40:14 +02005759 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005760 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005761}
5762
Johan Hedberg272d90d2012-02-09 15:26:12 +02005763int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005764 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005765{
5766 struct mgmt_ev_user_passkey_request ev;
5767
5768 BT_DBG("%s", hdev->name);
5769
Johan Hedberg272d90d2012-02-09 15:26:12 +02005770 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005771 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005772
5773 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005774 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005775}
5776
Brian Gix0df4c182011-11-16 13:53:13 -08005777static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005778 u8 link_type, u8 addr_type, u8 status,
5779 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005780{
5781 struct pending_cmd *cmd;
5782 struct mgmt_rp_user_confirm_reply rp;
5783 int err;
5784
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005785 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005786 if (!cmd)
5787 return -ENOENT;
5788
Johan Hedberg272d90d2012-02-09 15:26:12 +02005789 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005790 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005791 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005792 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005793
Johan Hedberga664b5b2011-02-19 12:06:02 -03005794 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005795
5796 return err;
5797}
5798
Johan Hedberg744cf192011-11-08 20:40:14 +02005799int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005800 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005801{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005802 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005803 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005804}
5805
Johan Hedberg272d90d2012-02-09 15:26:12 +02005806int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005807 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005808{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005809 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005810 status,
5811 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005812}
Johan Hedberg2a611692011-02-19 12:06:00 -03005813
Brian Gix604086b2011-11-23 08:28:33 -08005814int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005815 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005816{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005817 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005818 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005819}
5820
Johan Hedberg272d90d2012-02-09 15:26:12 +02005821int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005822 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005823{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005824 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005825 status,
5826 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005827}
5828
Johan Hedberg92a25252012-09-06 18:39:26 +03005829int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5830 u8 link_type, u8 addr_type, u32 passkey,
5831 u8 entered)
5832{
5833 struct mgmt_ev_passkey_notify ev;
5834
5835 BT_DBG("%s", hdev->name);
5836
5837 bacpy(&ev.addr.bdaddr, bdaddr);
5838 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5839 ev.passkey = __cpu_to_le32(passkey);
5840 ev.entered = entered;
5841
5842 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5843}
5844
Marcel Holtmanne5460992013-10-15 14:26:23 -07005845void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5846 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005847{
5848 struct mgmt_ev_auth_failed ev;
5849
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005850 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005851 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005852 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005853
Marcel Holtmanne5460992013-10-15 14:26:23 -07005854 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005855}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005856
Marcel Holtmann464996a2013-10-15 14:26:24 -07005857void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005858{
5859 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005860 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005861
5862 if (status) {
5863 u8 mgmt_err = mgmt_status(status);
5864 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005865 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005866 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005867 }
5868
Marcel Holtmann464996a2013-10-15 14:26:24 -07005869 if (test_bit(HCI_AUTH, &hdev->flags))
5870 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5871 &hdev->dev_flags);
5872 else
5873 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5874 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005875
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005876 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005877 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005878
Johan Hedberg47990ea2012-02-22 11:58:37 +02005879 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005880 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005881
5882 if (match.sk)
5883 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005884}
5885
Johan Hedberg890ea892013-03-15 17:06:52 -05005886static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005887{
Johan Hedberg890ea892013-03-15 17:06:52 -05005888 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005889 struct hci_cp_write_eir cp;
5890
Johan Hedberg976eb202012-10-24 21:12:01 +03005891 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005892 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005893
Johan Hedbergc80da272012-02-22 15:38:48 +02005894 memset(hdev->eir, 0, sizeof(hdev->eir));
5895
Johan Hedbergcacaf522012-02-21 00:52:42 +02005896 memset(&cp, 0, sizeof(cp));
5897
Johan Hedberg890ea892013-03-15 17:06:52 -05005898 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005899}
5900
Marcel Holtmann3e248562013-10-15 14:26:25 -07005901void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005902{
5903 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005904 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005905 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005906
5907 if (status) {
5908 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005909
5910 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005911 &hdev->dev_flags)) {
5912 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005913 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005914 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005915
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005916 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5917 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005918 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005919 }
5920
5921 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005922 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005923 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005924 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5925 if (!changed)
5926 changed = test_and_clear_bit(HCI_HS_ENABLED,
5927 &hdev->dev_flags);
5928 else
5929 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005930 }
5931
5932 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5933
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005934 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005935 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005936
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005937 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005938 sock_put(match.sk);
5939
Johan Hedberg890ea892013-03-15 17:06:52 -05005940 hci_req_init(&req, hdev);
5941
Johan Hedberg37699722014-06-24 14:00:27 +03005942 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5943 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
5944 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
5945 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05005946 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005947 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05005948 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005949 }
Johan Hedberg890ea892013-03-15 17:06:52 -05005950
5951 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005952}
5953
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005954void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5955{
5956 struct cmd_lookup match = { NULL, hdev };
5957 bool changed = false;
5958
5959 if (status) {
5960 u8 mgmt_err = mgmt_status(status);
5961
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005962 if (enable) {
5963 if (test_and_clear_bit(HCI_SC_ENABLED,
5964 &hdev->dev_flags))
5965 new_settings(hdev, NULL);
5966 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5967 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005968
5969 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5970 cmd_status_rsp, &mgmt_err);
5971 return;
5972 }
5973
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005974 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005975 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005976 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005977 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005978 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5979 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005980
5981 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5982 settings_rsp, &match);
5983
5984 if (changed)
5985 new_settings(hdev, match.sk);
5986
5987 if (match.sk)
5988 sock_put(match.sk);
5989}
5990
Johan Hedberg92da6092013-03-15 17:06:55 -05005991static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005992{
5993 struct cmd_lookup *match = data;
5994
Johan Hedberg90e70452012-02-23 23:09:40 +02005995 if (match->sk == NULL) {
5996 match->sk = cmd->sk;
5997 sock_hold(match->sk);
5998 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005999}
6000
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006001void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6002 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006003{
Johan Hedberg90e70452012-02-23 23:09:40 +02006004 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006005
Johan Hedberg92da6092013-03-15 17:06:55 -05006006 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6007 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6008 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006009
6010 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006011 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6012 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006013
6014 if (match.sk)
6015 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006016}
6017
Marcel Holtmann7667da32013-10-15 14:26:27 -07006018void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006019{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006020 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006021 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006022
Johan Hedberg13928972013-03-15 17:07:00 -05006023 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006024 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006025
6026 memset(&ev, 0, sizeof(ev));
6027 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006028 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006029
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006030 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006031 if (!cmd) {
6032 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006033
Johan Hedberg13928972013-03-15 17:07:00 -05006034 /* If this is a HCI command related to powering on the
6035 * HCI dev don't send any mgmt signals.
6036 */
6037 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006038 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006039 }
6040
Marcel Holtmann7667da32013-10-15 14:26:27 -07006041 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6042 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006043}
Szymon Jancc35938b2011-03-22 13:12:21 +01006044
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006045void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6046 u8 *randomizer192, u8 *hash256,
6047 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006048{
6049 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006050
Johan Hedberg744cf192011-11-08 20:40:14 +02006051 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006052
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006053 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006054 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006055 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006056
6057 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006058 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6059 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006060 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006061 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6062 hash256 && randomizer256) {
6063 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006064
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006065 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6066 memcpy(rp.randomizer192, randomizer192,
6067 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006068
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006069 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6070 memcpy(rp.randomizer256, randomizer256,
6071 sizeof(rp.randomizer256));
6072
6073 cmd_complete(cmd->sk, hdev->id,
6074 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6075 &rp, sizeof(rp));
6076 } else {
6077 struct mgmt_rp_read_local_oob_data rp;
6078
6079 memcpy(rp.hash, hash192, sizeof(rp.hash));
6080 memcpy(rp.randomizer, randomizer192,
6081 sizeof(rp.randomizer));
6082
6083 cmd_complete(cmd->sk, hdev->id,
6084 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6085 &rp, sizeof(rp));
6086 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006087 }
6088
6089 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006090}
Johan Hedberge17acd42011-03-30 23:57:16 +03006091
Marcel Holtmann901801b2013-10-06 23:55:51 -07006092void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02006093 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
6094 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006095 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006096{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006097 char buf[512];
6098 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006099 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006100 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006101
Andre Guedes12602d02013-04-30 15:29:40 -03006102 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006103 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006104
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006105 /* Make sure that the buffer is big enough. The 5 extra bytes
6106 * are for the potential CoD field.
6107 */
6108 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006109 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006110
Johan Hedberg1dc06092012-01-15 21:01:23 +02006111 memset(buf, 0, sizeof(buf));
6112
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006113 irk = hci_get_irk(hdev, bdaddr, addr_type);
6114 if (irk) {
6115 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6116 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6117 } else {
6118 bacpy(&ev->addr.bdaddr, bdaddr);
6119 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6120 }
6121
Johan Hedberge319d2e2012-01-15 19:51:59 +02006122 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02006123 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006124 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02006125 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006126 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03006127
Johan Hedberg1dc06092012-01-15 21:01:23 +02006128 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006129 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006130
Johan Hedberg1dc06092012-01-15 21:01:23 +02006131 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6132 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006133 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006134
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006135 if (scan_rsp_len > 0)
6136 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6137
6138 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6139 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006140
Marcel Holtmann901801b2013-10-06 23:55:51 -07006141 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006142}
Johan Hedberga88a9652011-03-30 13:18:12 +03006143
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006144void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6145 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006146{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006147 struct mgmt_ev_device_found *ev;
6148 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6149 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006150
Johan Hedbergb644ba32012-01-17 21:48:47 +02006151 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006152
Johan Hedbergb644ba32012-01-17 21:48:47 +02006153 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006154
Johan Hedbergb644ba32012-01-17 21:48:47 +02006155 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006156 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006157 ev->rssi = rssi;
6158
6159 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006160 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006161
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006162 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006163
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006164 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006165}
Johan Hedberg314b2382011-04-27 10:29:57 -04006166
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006167void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006168{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006169 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006170 struct pending_cmd *cmd;
6171
Andre Guedes343fb142011-11-22 17:14:19 -03006172 BT_DBG("%s discovering %u", hdev->name, discovering);
6173
Johan Hedberg164a6e72011-11-01 17:06:44 +02006174 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006175 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006176 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006177 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006178
6179 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006180 u8 type = hdev->discovery.type;
6181
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006182 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6183 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006184 mgmt_pending_remove(cmd);
6185 }
6186
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006187 memset(&ev, 0, sizeof(ev));
6188 ev.type = hdev->discovery.type;
6189 ev.discovering = discovering;
6190
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006191 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006192}
Antti Julku5e762442011-08-25 16:48:02 +03006193
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006194int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006195{
6196 struct pending_cmd *cmd;
6197 struct mgmt_ev_device_blocked ev;
6198
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006199 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006200
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006201 bacpy(&ev.addr.bdaddr, bdaddr);
6202 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006203
Johan Hedberg744cf192011-11-08 20:40:14 +02006204 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006205 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006206}
6207
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006208int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006209{
6210 struct pending_cmd *cmd;
6211 struct mgmt_ev_device_unblocked ev;
6212
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006213 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006214
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006215 bacpy(&ev.addr.bdaddr, bdaddr);
6216 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006217
Johan Hedberg744cf192011-11-08 20:40:14 +02006218 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006219 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006220}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006221
6222static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6223{
6224 BT_DBG("%s status %u", hdev->name, status);
6225
6226 /* Clear the advertising mgmt setting if we failed to re-enable it */
6227 if (status) {
6228 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006229 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006230 }
6231}
6232
6233void mgmt_reenable_advertising(struct hci_dev *hdev)
6234{
6235 struct hci_request req;
6236
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006237 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006238 return;
6239
6240 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6241 return;
6242
6243 hci_req_init(&req, hdev);
6244 enable_advertising(&req);
6245
6246 /* If this fails we have no option but to let user space know
6247 * that we've disabled advertising.
6248 */
6249 if (hci_req_run(&req, adv_enable_complete) < 0) {
6250 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006251 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006252 }
6253}