blob: 41b1aec0c5dc64e7597802d4a05f49d4fb6dc681 [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 Holtmannfee746b2014-06-29 12:13:05 +0200350 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
351 continue;
352
Marcel Holtmann1514b892013-10-06 08:25:01 -0700353 if (d->dev_type == HCI_BREDR) {
354 rp->index[count++] = cpu_to_le16(d->id);
355 BT_DBG("Added hci%u", d->id);
356 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200357 }
358
Johan Hedberg476e44c2012-10-19 20:10:46 +0300359 rp->num_controllers = cpu_to_le16(count);
360 rp_len = sizeof(*rp) + (2 * count);
361
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 read_unlock(&hci_dev_list_lock);
363
Johan Hedbergaee9b212012-02-18 15:07:59 +0200364 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300365 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366
Johan Hedberga38528f2011-01-22 06:46:43 +0200367 kfree(rp);
368
369 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200370}
371
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200373{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200374 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200375
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200376 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200377 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800378 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200379
Andre Guedesed3fa312012-07-24 15:03:46 -0300380 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300381 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500382 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
383 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300384 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200385 settings |= MGMT_SETTING_BREDR;
386 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700387
388 if (lmp_ssp_capable(hdev)) {
389 settings |= MGMT_SETTING_SSP;
390 settings |= MGMT_SETTING_HS;
391 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800392
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800393 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200394 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800395 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700396 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100397
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300398 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200399 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300400 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200401 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300402 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200403
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200404 return settings;
405}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200406
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200407static u32 get_current_settings(struct hci_dev *hdev)
408{
409 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200410
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200411 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100412 settings |= MGMT_SETTING_POWERED;
413
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200414 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200415 settings |= MGMT_SETTING_CONNECTABLE;
416
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500417 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
418 settings |= MGMT_SETTING_FAST_CONNECTABLE;
419
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200420 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200421 settings |= MGMT_SETTING_DISCOVERABLE;
422
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200423 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200424 settings |= MGMT_SETTING_PAIRABLE;
425
Johan Hedberg56f87902013-10-02 13:43:13 +0300426 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200427 settings |= MGMT_SETTING_BREDR;
428
Johan Hedberg06199cf2012-02-22 16:37:11 +0200429 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200430 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200431
Johan Hedberg47990ea2012-02-22 11:58:37 +0200432 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200433 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200434
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200435 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200436 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200437
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200438 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
439 settings |= MGMT_SETTING_HS;
440
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200441 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300442 settings |= MGMT_SETTING_ADVERTISING;
443
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800444 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
445 settings |= MGMT_SETTING_SECURE_CONN;
446
Johan Hedberg0663b292014-06-24 13:15:50 +0300447 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800448 settings |= MGMT_SETTING_DEBUG_KEYS;
449
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200450 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
451 settings |= MGMT_SETTING_PRIVACY;
452
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200453 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200454}
455
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300456#define PNP_INFO_SVCLASS_ID 0x1200
457
Johan Hedberg213202e2013-01-27 00:31:33 +0200458static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
459{
460 u8 *ptr = data, *uuids_start = NULL;
461 struct bt_uuid *uuid;
462
463 if (len < 4)
464 return ptr;
465
466 list_for_each_entry(uuid, &hdev->uuids, list) {
467 u16 uuid16;
468
469 if (uuid->size != 16)
470 continue;
471
472 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
473 if (uuid16 < 0x1100)
474 continue;
475
476 if (uuid16 == PNP_INFO_SVCLASS_ID)
477 continue;
478
479 if (!uuids_start) {
480 uuids_start = ptr;
481 uuids_start[0] = 1;
482 uuids_start[1] = EIR_UUID16_ALL;
483 ptr += 2;
484 }
485
486 /* Stop if not enough space to put next UUID */
487 if ((ptr - data) + sizeof(u16) > len) {
488 uuids_start[1] = EIR_UUID16_SOME;
489 break;
490 }
491
492 *ptr++ = (uuid16 & 0x00ff);
493 *ptr++ = (uuid16 & 0xff00) >> 8;
494 uuids_start[0] += sizeof(uuid16);
495 }
496
497 return ptr;
498}
499
Johan Hedbergcdf19632013-01-27 00:31:34 +0200500static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
501{
502 u8 *ptr = data, *uuids_start = NULL;
503 struct bt_uuid *uuid;
504
505 if (len < 6)
506 return ptr;
507
508 list_for_each_entry(uuid, &hdev->uuids, list) {
509 if (uuid->size != 32)
510 continue;
511
512 if (!uuids_start) {
513 uuids_start = ptr;
514 uuids_start[0] = 1;
515 uuids_start[1] = EIR_UUID32_ALL;
516 ptr += 2;
517 }
518
519 /* Stop if not enough space to put next UUID */
520 if ((ptr - data) + sizeof(u32) > len) {
521 uuids_start[1] = EIR_UUID32_SOME;
522 break;
523 }
524
525 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
526 ptr += sizeof(u32);
527 uuids_start[0] += sizeof(u32);
528 }
529
530 return ptr;
531}
532
Johan Hedbergc00d5752013-01-27 00:31:35 +0200533static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
534{
535 u8 *ptr = data, *uuids_start = NULL;
536 struct bt_uuid *uuid;
537
538 if (len < 18)
539 return ptr;
540
541 list_for_each_entry(uuid, &hdev->uuids, list) {
542 if (uuid->size != 128)
543 continue;
544
545 if (!uuids_start) {
546 uuids_start = ptr;
547 uuids_start[0] = 1;
548 uuids_start[1] = EIR_UUID128_ALL;
549 ptr += 2;
550 }
551
552 /* Stop if not enough space to put next UUID */
553 if ((ptr - data) + 16 > len) {
554 uuids_start[1] = EIR_UUID128_SOME;
555 break;
556 }
557
558 memcpy(ptr, uuid->uuid, 16);
559 ptr += 16;
560 uuids_start[0] += 16;
561 }
562
563 return ptr;
564}
565
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300566static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
567{
568 struct pending_cmd *cmd;
569
570 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
571 if (cmd->opcode == opcode)
572 return cmd;
573 }
574
575 return NULL;
576}
577
Johan Hedberg95868422014-06-28 17:54:07 +0300578static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
579 struct hci_dev *hdev,
580 const void *data)
581{
582 struct pending_cmd *cmd;
583
584 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
585 if (cmd->user_data != data)
586 continue;
587 if (cmd->opcode == opcode)
588 return cmd;
589 }
590
591 return NULL;
592}
593
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700594static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
595{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700596 u8 ad_len = 0;
597 size_t name_len;
598
599 name_len = strlen(hdev->dev_name);
600 if (name_len > 0) {
601 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
602
603 if (name_len > max_len) {
604 name_len = max_len;
605 ptr[1] = EIR_NAME_SHORT;
606 } else
607 ptr[1] = EIR_NAME_COMPLETE;
608
609 ptr[0] = name_len + 1;
610
611 memcpy(ptr + 2, hdev->dev_name, name_len);
612
613 ad_len += (name_len + 2);
614 ptr += (name_len + 2);
615 }
616
617 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700618}
619
620static void update_scan_rsp_data(struct hci_request *req)
621{
622 struct hci_dev *hdev = req->hdev;
623 struct hci_cp_le_set_scan_rsp_data cp;
624 u8 len;
625
Johan Hedberg7751ef12013-10-19 23:38:15 +0300626 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700627 return;
628
629 memset(&cp, 0, sizeof(cp));
630
631 len = create_scan_rsp_data(hdev, cp.data);
632
Johan Hedbergeb438b52013-10-16 15:31:07 +0300633 if (hdev->scan_rsp_data_len == len &&
634 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700635 return;
636
Johan Hedbergeb438b52013-10-16 15:31:07 +0300637 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
638 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700639
640 cp.length = len;
641
642 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
643}
644
Johan Hedberg9a43e252013-10-20 19:00:07 +0300645static u8 get_adv_discov_flags(struct hci_dev *hdev)
646{
647 struct pending_cmd *cmd;
648
649 /* If there's a pending mgmt command the flags will not yet have
650 * their final values, so check for this first.
651 */
652 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
653 if (cmd) {
654 struct mgmt_mode *cp = cmd->param;
655 if (cp->val == 0x01)
656 return LE_AD_GENERAL;
657 else if (cp->val == 0x02)
658 return LE_AD_LIMITED;
659 } else {
660 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
661 return LE_AD_LIMITED;
662 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
663 return LE_AD_GENERAL;
664 }
665
666 return 0;
667}
668
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700669static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700670{
671 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700672
Johan Hedberg9a43e252013-10-20 19:00:07 +0300673 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700674
Johan Hedberge8340042014-01-30 11:16:50 -0800675 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700676 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700677
678 if (flags) {
679 BT_DBG("adv flags 0x%02x", flags);
680
681 ptr[0] = 2;
682 ptr[1] = EIR_FLAGS;
683 ptr[2] = flags;
684
685 ad_len += 3;
686 ptr += 3;
687 }
688
689 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
690 ptr[0] = 2;
691 ptr[1] = EIR_TX_POWER;
692 ptr[2] = (u8) hdev->adv_tx_power;
693
694 ad_len += 3;
695 ptr += 3;
696 }
697
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700698 return ad_len;
699}
700
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700701static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700702{
703 struct hci_dev *hdev = req->hdev;
704 struct hci_cp_le_set_adv_data cp;
705 u8 len;
706
Johan Hedberg10994ce2013-10-19 23:38:16 +0300707 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700708 return;
709
710 memset(&cp, 0, sizeof(cp));
711
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700712 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700713
714 if (hdev->adv_data_len == len &&
715 memcmp(cp.data, hdev->adv_data, len) == 0)
716 return;
717
718 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
719 hdev->adv_data_len = len;
720
721 cp.length = len;
722
723 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
724}
725
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726static void create_eir(struct hci_dev *hdev, u8 *data)
727{
728 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300729 size_t name_len;
730
731 name_len = strlen(hdev->dev_name);
732
733 if (name_len > 0) {
734 /* EIR Data type */
735 if (name_len > 48) {
736 name_len = 48;
737 ptr[1] = EIR_NAME_SHORT;
738 } else
739 ptr[1] = EIR_NAME_COMPLETE;
740
741 /* EIR Data length */
742 ptr[0] = name_len + 1;
743
744 memcpy(ptr + 2, hdev->dev_name, name_len);
745
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300746 ptr += (name_len + 2);
747 }
748
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100749 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700750 ptr[0] = 2;
751 ptr[1] = EIR_TX_POWER;
752 ptr[2] = (u8) hdev->inq_tx_power;
753
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700754 ptr += 3;
755 }
756
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700757 if (hdev->devid_source > 0) {
758 ptr[0] = 9;
759 ptr[1] = EIR_DEVICE_ID;
760
761 put_unaligned_le16(hdev->devid_source, ptr + 2);
762 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
763 put_unaligned_le16(hdev->devid_product, ptr + 6);
764 put_unaligned_le16(hdev->devid_version, ptr + 8);
765
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700766 ptr += 10;
767 }
768
Johan Hedberg213202e2013-01-27 00:31:33 +0200769 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200770 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200771 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300772}
773
Johan Hedberg890ea892013-03-15 17:06:52 -0500774static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300775{
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777 struct hci_cp_write_eir cp;
778
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200779 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200781
Johan Hedberg976eb202012-10-24 21:12:01 +0300782 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500783 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300784
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200785 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500786 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300787
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200788 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500789 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300790
791 memset(&cp, 0, sizeof(cp));
792
793 create_eir(hdev, cp.data);
794
795 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300797
798 memcpy(hdev->eir, cp.data, sizeof(cp.data));
799
Johan Hedberg890ea892013-03-15 17:06:52 -0500800 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300801}
802
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200803static u8 get_service_classes(struct hci_dev *hdev)
804{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300805 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200806 u8 val = 0;
807
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300808 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200810
811 return val;
812}
813
Johan Hedberg890ea892013-03-15 17:06:52 -0500814static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200815{
Johan Hedberg890ea892013-03-15 17:06:52 -0500816 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 u8 cod[3];
818
819 BT_DBG("%s", hdev->name);
820
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200821 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500822 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200823
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300824 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
825 return;
826
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200827 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500828 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200829
830 cod[0] = hdev->minor_class;
831 cod[1] = hdev->major_class;
832 cod[2] = get_service_classes(hdev);
833
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700834 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
835 cod[1] |= 0x20;
836
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200837 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500838 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200839
Johan Hedberg890ea892013-03-15 17:06:52 -0500840 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200841}
842
Johan Hedberga4858cb2014-02-25 19:56:31 +0200843static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200844{
845 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200846
847 /* If there's a pending mgmt command the flag will not yet have
848 * it's final value, so check for this first.
849 */
850 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
851 if (cmd) {
852 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200854 }
855
Johan Hedberga4858cb2014-02-25 19:56:31 +0200856 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200857}
858
859static void enable_advertising(struct hci_request *req)
860{
861 struct hci_dev *hdev = req->hdev;
862 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200863 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200864 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200865
Johan Hedberg8d972502014-02-28 12:54:14 +0200866 /* Clear the HCI_ADVERTISING bit temporarily so that the
867 * hci_update_random_address knows that it's safe to go ahead
868 * and write a new random address. The flag will be set back on
869 * as soon as the SET_ADV_ENABLE HCI command completes.
870 */
871 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
872
Johan Hedberga4858cb2014-02-25 19:56:31 +0200873 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200874
Johan Hedberga4858cb2014-02-25 19:56:31 +0200875 /* Set require_privacy to true only when non-connectable
876 * advertising is used. In that case it is fine to use a
877 * non-resolvable private address.
878 */
879 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200880 return;
881
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800882 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700883 cp.min_interval = cpu_to_le16(0x0800);
884 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200885 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200886 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200887 cp.channel_map = hdev->le_adv_channel_map;
888
889 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
890
891 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
892}
893
894static void disable_advertising(struct hci_request *req)
895{
896 u8 enable = 0x00;
897
898 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
899}
900
Johan Hedberg7d785252011-12-15 00:47:39 +0200901static void service_cache_off(struct work_struct *work)
902{
903 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300904 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500905 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200906
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200907 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200908 return;
909
Johan Hedberg890ea892013-03-15 17:06:52 -0500910 hci_req_init(&req, hdev);
911
Johan Hedberg7d785252011-12-15 00:47:39 +0200912 hci_dev_lock(hdev);
913
Johan Hedberg890ea892013-03-15 17:06:52 -0500914 update_eir(&req);
915 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200916
917 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500918
919 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200920}
921
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200922static void rpa_expired(struct work_struct *work)
923{
924 struct hci_dev *hdev = container_of(work, struct hci_dev,
925 rpa_expired.work);
926 struct hci_request req;
927
928 BT_DBG("");
929
930 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
931
932 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
933 hci_conn_num(hdev, LE_LINK) > 0)
934 return;
935
936 /* The generation of a new RPA and programming it into the
937 * controller happens in the enable_advertising() function.
938 */
939
940 hci_req_init(&req, hdev);
941
942 disable_advertising(&req);
943 enable_advertising(&req);
944
945 hci_req_run(&req, NULL);
946}
947
Johan Hedberg6a919082012-02-28 06:17:26 +0200948static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200949{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200950 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200951 return;
952
Johan Hedberg4f87da82012-03-02 19:55:56 +0200953 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200954 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200955
Johan Hedberg4f87da82012-03-02 19:55:56 +0200956 /* Non-mgmt controlled devices get this bit set
957 * implicitly so that pairing works for them, however
958 * for mgmt we require user-space to explicitly enable
959 * it
960 */
961 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200962}
963
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200964static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300965 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200966{
967 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200968
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200969 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200970
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300971 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200972
Johan Hedberg03811012010-12-08 00:21:06 +0200973 memset(&rp, 0, sizeof(rp));
974
Johan Hedberg03811012010-12-08 00:21:06 +0200975 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200976
977 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200978 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200979
980 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
981 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
982
983 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200984
985 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200986 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200987
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300988 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200989
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200990 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300991 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200992}
993
994static void mgmt_pending_free(struct pending_cmd *cmd)
995{
996 sock_put(cmd->sk);
997 kfree(cmd->param);
998 kfree(cmd);
999}
1000
1001static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001002 struct hci_dev *hdev, void *data,
1003 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001004{
1005 struct pending_cmd *cmd;
1006
Johan Hedbergfca20012014-06-28 17:54:05 +03001007 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001008 if (!cmd)
1009 return NULL;
1010
1011 cmd->opcode = opcode;
1012 cmd->index = hdev->id;
1013
Andre Guedes12b94562012-06-07 19:05:45 -03001014 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001015 if (!cmd->param) {
1016 kfree(cmd);
1017 return NULL;
1018 }
1019
1020 if (data)
1021 memcpy(cmd->param, data, len);
1022
1023 cmd->sk = sk;
1024 sock_hold(sk);
1025
1026 list_add(&cmd->list, &hdev->mgmt_pending);
1027
1028 return cmd;
1029}
1030
1031static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001032 void (*cb)(struct pending_cmd *cmd,
1033 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001034 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001035{
Andre Guedesa3d09352013-02-01 11:21:30 -03001036 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001037
Andre Guedesa3d09352013-02-01 11:21:30 -03001038 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001039 if (opcode > 0 && cmd->opcode != opcode)
1040 continue;
1041
1042 cb(cmd, data);
1043 }
1044}
1045
Johan Hedberg03811012010-12-08 00:21:06 +02001046static void mgmt_pending_remove(struct pending_cmd *cmd)
1047{
1048 list_del(&cmd->list);
1049 mgmt_pending_free(cmd);
1050}
1051
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001052static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001053{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001054 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001055
Johan Hedbergaee9b212012-02-18 15:07:59 +02001056 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001057 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001058}
1059
Johan Hedberg8b064a32014-02-24 14:52:22 +02001060static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1061{
1062 BT_DBG("%s status 0x%02x", hdev->name, status);
1063
Johan Hedberga3172b72014-02-28 09:33:44 +02001064 if (hci_conn_count(hdev) == 0) {
1065 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001066 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001067 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001068}
1069
Johan Hedberg21a60d32014-06-10 14:05:58 +03001070static void hci_stop_discovery(struct hci_request *req)
1071{
1072 struct hci_dev *hdev = req->hdev;
1073 struct hci_cp_remote_name_req_cancel cp;
1074 struct inquiry_entry *e;
1075
1076 switch (hdev->discovery.state) {
1077 case DISCOVERY_FINDING:
1078 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1079 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1080 } else {
1081 cancel_delayed_work(&hdev->le_scan_disable);
1082 hci_req_add_le_scan_disable(req);
1083 }
1084
1085 break;
1086
1087 case DISCOVERY_RESOLVING:
1088 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1089 NAME_PENDING);
1090 if (!e)
1091 return;
1092
1093 bacpy(&cp.bdaddr, &e->data.bdaddr);
1094 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1095 &cp);
1096
1097 break;
1098
1099 default:
1100 /* Passive scanning */
1101 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1102 hci_req_add_le_scan_disable(req);
1103 break;
1104 }
1105}
1106
Johan Hedberg8b064a32014-02-24 14:52:22 +02001107static int clean_up_hci_state(struct hci_dev *hdev)
1108{
1109 struct hci_request req;
1110 struct hci_conn *conn;
1111
1112 hci_req_init(&req, hdev);
1113
1114 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1115 test_bit(HCI_PSCAN, &hdev->flags)) {
1116 u8 scan = 0x00;
1117 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1118 }
1119
1120 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1121 disable_advertising(&req);
1122
Johan Hedbergf8680f12014-06-10 14:05:59 +03001123 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001124
1125 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1126 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001127 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001128
Johan Hedbergc9910d02014-02-27 14:35:12 +02001129 switch (conn->state) {
1130 case BT_CONNECTED:
1131 case BT_CONFIG:
1132 dc.handle = cpu_to_le16(conn->handle);
1133 dc.reason = 0x15; /* Terminated due to Power Off */
1134 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1135 break;
1136 case BT_CONNECT:
1137 if (conn->type == LE_LINK)
1138 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1139 0, NULL);
1140 else if (conn->type == ACL_LINK)
1141 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1142 6, &conn->dst);
1143 break;
1144 case BT_CONNECT2:
1145 bacpy(&rej.bdaddr, &conn->dst);
1146 rej.reason = 0x15; /* Terminated due to Power Off */
1147 if (conn->type == ACL_LINK)
1148 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1149 sizeof(rej), &rej);
1150 else if (conn->type == SCO_LINK)
1151 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1152 sizeof(rej), &rej);
1153 break;
1154 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001155 }
1156
1157 return hci_req_run(&req, clean_up_hci_complete);
1158}
1159
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001160static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001161 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001162{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001163 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001164 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001165 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001167 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
Johan Hedberga7e80f22013-01-09 16:05:19 +02001169 if (cp->val != 0x00 && cp->val != 0x01)
1170 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1171 MGMT_STATUS_INVALID_PARAMS);
1172
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001173 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001174
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001175 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1176 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1177 MGMT_STATUS_BUSY);
1178 goto failed;
1179 }
1180
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001181 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1182 cancel_delayed_work(&hdev->power_off);
1183
1184 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001185 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1186 data, len);
1187 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001188 goto failed;
1189 }
1190 }
1191
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001192 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001193 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001194 goto failed;
1195 }
1196
Johan Hedberg03811012010-12-08 00:21:06 +02001197 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1198 if (!cmd) {
1199 err = -ENOMEM;
1200 goto failed;
1201 }
1202
Johan Hedberg8b064a32014-02-24 14:52:22 +02001203 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001204 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001205 err = 0;
1206 } else {
1207 /* Disconnect connections, stop scans, etc */
1208 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001209 if (!err)
1210 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1211 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001212
Johan Hedberg8b064a32014-02-24 14:52:22 +02001213 /* ENODATA means there were no HCI commands queued */
1214 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001215 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001216 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1217 err = 0;
1218 }
1219 }
Johan Hedberg03811012010-12-08 00:21:06 +02001220
1221failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001222 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001223 return err;
1224}
1225
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001226static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1227 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001228{
1229 struct sk_buff *skb;
1230 struct mgmt_hdr *hdr;
1231
Andre Guedes790eff42012-06-07 19:05:46 -03001232 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001233 if (!skb)
1234 return -ENOMEM;
1235
1236 hdr = (void *) skb_put(skb, sizeof(*hdr));
1237 hdr->opcode = cpu_to_le16(event);
1238 if (hdev)
1239 hdr->index = cpu_to_le16(hdev->id);
1240 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001241 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001242 hdr->len = cpu_to_le16(data_len);
1243
1244 if (data)
1245 memcpy(skb_put(skb, data_len), data, data_len);
1246
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001247 /* Time stamp */
1248 __net_timestamp(skb);
1249
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001250 hci_send_to_control(skb, skip_sk);
1251 kfree_skb(skb);
1252
1253 return 0;
1254}
1255
1256static int new_settings(struct hci_dev *hdev, struct sock *skip)
1257{
1258 __le32 ev;
1259
1260 ev = cpu_to_le32(get_current_settings(hdev));
1261
1262 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1263}
1264
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001265struct cmd_lookup {
1266 struct sock *sk;
1267 struct hci_dev *hdev;
1268 u8 mgmt_status;
1269};
1270
1271static void settings_rsp(struct pending_cmd *cmd, void *data)
1272{
1273 struct cmd_lookup *match = data;
1274
1275 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1276
1277 list_del(&cmd->list);
1278
1279 if (match->sk == NULL) {
1280 match->sk = cmd->sk;
1281 sock_hold(match->sk);
1282 }
1283
1284 mgmt_pending_free(cmd);
1285}
1286
1287static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1288{
1289 u8 *status = data;
1290
1291 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1292 mgmt_pending_remove(cmd);
1293}
1294
Johan Hedberge6fe7982013-10-02 15:45:22 +03001295static u8 mgmt_bredr_support(struct hci_dev *hdev)
1296{
1297 if (!lmp_bredr_capable(hdev))
1298 return MGMT_STATUS_NOT_SUPPORTED;
1299 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1300 return MGMT_STATUS_REJECTED;
1301 else
1302 return MGMT_STATUS_SUCCESS;
1303}
1304
1305static u8 mgmt_le_support(struct hci_dev *hdev)
1306{
1307 if (!lmp_le_capable(hdev))
1308 return MGMT_STATUS_NOT_SUPPORTED;
1309 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1310 return MGMT_STATUS_REJECTED;
1311 else
1312 return MGMT_STATUS_SUCCESS;
1313}
1314
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001315static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1316{
1317 struct pending_cmd *cmd;
1318 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001319 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001320 bool changed;
1321
1322 BT_DBG("status 0x%02x", status);
1323
1324 hci_dev_lock(hdev);
1325
1326 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1327 if (!cmd)
1328 goto unlock;
1329
1330 if (status) {
1331 u8 mgmt_err = mgmt_status(status);
1332 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001333 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001334 goto remove_cmd;
1335 }
1336
1337 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001338 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001339 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1340 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001341
1342 if (hdev->discov_timeout > 0) {
1343 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1344 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1345 to);
1346 }
1347 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001348 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1349 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001350 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001351
1352 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1353
1354 if (changed)
1355 new_settings(hdev, cmd->sk);
1356
Marcel Holtmann970ba522013-10-15 06:33:57 -07001357 /* When the discoverable mode gets changed, make sure
1358 * that class of device has the limited discoverable
1359 * bit correctly set.
1360 */
1361 hci_req_init(&req, hdev);
1362 update_class(&req);
1363 hci_req_run(&req, NULL);
1364
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001365remove_cmd:
1366 mgmt_pending_remove(cmd);
1367
1368unlock:
1369 hci_dev_unlock(hdev);
1370}
1371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001373 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001375 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001376 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001377 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001378 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001379 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001380 int err;
1381
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001382 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001383
Johan Hedberg9a43e252013-10-20 19:00:07 +03001384 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1385 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001386 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001387 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001388
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001389 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001390 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1391 MGMT_STATUS_INVALID_PARAMS);
1392
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001393 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001394
1395 /* Disabling discoverable requires that no timeout is set,
1396 * and enabling limited discoverable requires a timeout.
1397 */
1398 if ((cp->val == 0x00 && timeout > 0) ||
1399 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001400 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001401 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001402
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001403 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001404
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001405 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001406 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001407 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001408 goto failed;
1409 }
1410
1411 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001412 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001413 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001414 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001415 goto failed;
1416 }
1417
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001418 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001419 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001420 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001421 goto failed;
1422 }
1423
1424 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001425 bool changed = false;
1426
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001427 /* Setting limited discoverable when powered off is
1428 * not a valid operation since it requires a timeout
1429 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1430 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001431 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1432 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1433 changed = true;
1434 }
1435
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001436 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001437 if (err < 0)
1438 goto failed;
1439
1440 if (changed)
1441 err = new_settings(hdev, sk);
1442
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001443 goto failed;
1444 }
1445
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001446 /* If the current mode is the same, then just update the timeout
1447 * value with the new value. And if only the timeout gets updated,
1448 * then no need for any HCI transactions.
1449 */
1450 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1451 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1452 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001453 cancel_delayed_work(&hdev->discov_off);
1454 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001455
Marcel Holtmann36261542013-10-15 08:28:51 -07001456 if (cp->val && hdev->discov_timeout > 0) {
1457 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001458 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001459 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001460 }
1461
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001462 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001463 goto failed;
1464 }
1465
1466 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1467 if (!cmd) {
1468 err = -ENOMEM;
1469 goto failed;
1470 }
1471
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001472 /* Cancel any potential discoverable timeout that might be
1473 * still active and store new timeout value. The arming of
1474 * the timeout happens in the complete handler.
1475 */
1476 cancel_delayed_work(&hdev->discov_off);
1477 hdev->discov_timeout = timeout;
1478
Johan Hedbergb456f872013-10-19 23:38:22 +03001479 /* Limited discoverable mode */
1480 if (cp->val == 0x02)
1481 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1482 else
1483 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1484
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001485 hci_req_init(&req, hdev);
1486
Johan Hedberg9a43e252013-10-20 19:00:07 +03001487 /* The procedure for LE-only controllers is much simpler - just
1488 * update the advertising data.
1489 */
1490 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1491 goto update_ad;
1492
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001493 scan = SCAN_PAGE;
1494
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001495 if (cp->val) {
1496 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001497
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001498 if (cp->val == 0x02) {
1499 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001500 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001501 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1502 hci_cp.iac_lap[1] = 0x8b;
1503 hci_cp.iac_lap[2] = 0x9e;
1504 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1505 hci_cp.iac_lap[4] = 0x8b;
1506 hci_cp.iac_lap[5] = 0x9e;
1507 } else {
1508 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001509 hci_cp.num_iac = 1;
1510 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1511 hci_cp.iac_lap[1] = 0x8b;
1512 hci_cp.iac_lap[2] = 0x9e;
1513 }
1514
1515 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1516 (hci_cp.num_iac * 3) + 1, &hci_cp);
1517
1518 scan |= SCAN_INQUIRY;
1519 } else {
1520 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1521 }
1522
1523 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001524
Johan Hedberg9a43e252013-10-20 19:00:07 +03001525update_ad:
1526 update_adv_data(&req);
1527
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001529 if (err < 0)
1530 mgmt_pending_remove(cmd);
1531
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001532failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001533 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001534 return err;
1535}
1536
Johan Hedberg406d7802013-03-15 17:07:09 -05001537static void write_fast_connectable(struct hci_request *req, bool enable)
1538{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001539 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001540 struct hci_cp_write_page_scan_activity acp;
1541 u8 type;
1542
Johan Hedberg547003b2013-10-21 16:51:53 +03001543 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1544 return;
1545
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001546 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1547 return;
1548
Johan Hedberg406d7802013-03-15 17:07:09 -05001549 if (enable) {
1550 type = PAGE_SCAN_TYPE_INTERLACED;
1551
1552 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001553 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001554 } else {
1555 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1556
1557 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001558 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001559 }
1560
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001561 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001562
Johan Hedbergbd98b992013-03-15 17:07:13 -05001563 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1564 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1565 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1566 sizeof(acp), &acp);
1567
1568 if (hdev->page_scan_type != type)
1569 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001570}
1571
Johan Hedberg2b76f452013-03-15 17:07:04 -05001572static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1573{
1574 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001575 struct mgmt_mode *cp;
1576 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001577
1578 BT_DBG("status 0x%02x", status);
1579
1580 hci_dev_lock(hdev);
1581
1582 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1583 if (!cmd)
1584 goto unlock;
1585
Johan Hedberg37438c12013-10-14 16:20:05 +03001586 if (status) {
1587 u8 mgmt_err = mgmt_status(status);
1588 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1589 goto remove_cmd;
1590 }
1591
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001592 cp = cmd->param;
1593 if (cp->val)
1594 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1595 else
1596 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1597
Johan Hedberg2b76f452013-03-15 17:07:04 -05001598 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1599
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001600 if (changed)
1601 new_settings(hdev, cmd->sk);
1602
Johan Hedberg37438c12013-10-14 16:20:05 +03001603remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001604 mgmt_pending_remove(cmd);
1605
1606unlock:
1607 hci_dev_unlock(hdev);
1608}
1609
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001610static int set_connectable_update_settings(struct hci_dev *hdev,
1611 struct sock *sk, u8 val)
1612{
1613 bool changed = false;
1614 int err;
1615
1616 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1617 changed = true;
1618
1619 if (val) {
1620 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1621 } else {
1622 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1623 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1624 }
1625
1626 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1627 if (err < 0)
1628 return err;
1629
1630 if (changed)
1631 return new_settings(hdev, sk);
1632
1633 return 0;
1634}
1635
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001636static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001637 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001638{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001639 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001640 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001641 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001642 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001643 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001644
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001645 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001646
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001647 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1648 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001649 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001650 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001651
Johan Hedberga7e80f22013-01-09 16:05:19 +02001652 if (cp->val != 0x00 && cp->val != 0x01)
1653 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1654 MGMT_STATUS_INVALID_PARAMS);
1655
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001656 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001657
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001658 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001659 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001660 goto failed;
1661 }
1662
1663 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001664 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001665 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001666 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001667 goto failed;
1668 }
1669
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001670 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1671 if (!cmd) {
1672 err = -ENOMEM;
1673 goto failed;
1674 }
1675
Johan Hedberg2b76f452013-03-15 17:07:04 -05001676 hci_req_init(&req, hdev);
1677
Johan Hedberg9a43e252013-10-20 19:00:07 +03001678 /* If BR/EDR is not enabled and we disable advertising as a
1679 * by-product of disabling connectable, we need to update the
1680 * advertising flags.
1681 */
1682 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1683 if (!cp->val) {
1684 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1685 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1686 }
1687 update_adv_data(&req);
1688 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001689 if (cp->val) {
1690 scan = SCAN_PAGE;
1691 } else {
1692 scan = 0;
1693
1694 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001695 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001696 cancel_delayed_work(&hdev->discov_off);
1697 }
1698
1699 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1700 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001701
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001702 /* If we're going from non-connectable to connectable or
1703 * vice-versa when fast connectable is enabled ensure that fast
1704 * connectable gets disabled. write_fast_connectable won't do
1705 * anything if the page scan parameters are already what they
1706 * should be.
1707 */
1708 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001709 write_fast_connectable(&req, false);
1710
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001711 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1712 hci_conn_num(hdev, LE_LINK) == 0) {
1713 disable_advertising(&req);
1714 enable_advertising(&req);
1715 }
1716
Johan Hedberg2b76f452013-03-15 17:07:04 -05001717 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001718 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001720 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001721 err = set_connectable_update_settings(hdev, sk,
1722 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001723 goto failed;
1724 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725
1726failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001727 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001728 return err;
1729}
1730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001731static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001732 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001733{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001734 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001735 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001736 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001738 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001739
Johan Hedberga7e80f22013-01-09 16:05:19 +02001740 if (cp->val != 0x00 && cp->val != 0x01)
1741 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1742 MGMT_STATUS_INVALID_PARAMS);
1743
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001744 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001745
1746 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001747 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001748 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001749 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001750
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001751 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001752 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001753 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001754
Marcel Holtmann55594352013-10-06 16:11:57 -07001755 if (changed)
1756 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001757
Marcel Holtmann55594352013-10-06 16:11:57 -07001758unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001759 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001760 return err;
1761}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001762
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001763static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1764 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001765{
1766 struct mgmt_mode *cp = data;
1767 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001768 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001769 int err;
1770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001771 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001772
Johan Hedberge6fe7982013-10-02 15:45:22 +03001773 status = mgmt_bredr_support(hdev);
1774 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001775 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001776 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001777
Johan Hedberga7e80f22013-01-09 16:05:19 +02001778 if (cp->val != 0x00 && cp->val != 0x01)
1779 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1780 MGMT_STATUS_INVALID_PARAMS);
1781
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001782 hci_dev_lock(hdev);
1783
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001784 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001785 bool changed = false;
1786
1787 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001788 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001789 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1790 changed = true;
1791 }
1792
1793 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1794 if (err < 0)
1795 goto failed;
1796
1797 if (changed)
1798 err = new_settings(hdev, sk);
1799
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001800 goto failed;
1801 }
1802
1803 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001804 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001805 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001806 goto failed;
1807 }
1808
1809 val = !!cp->val;
1810
1811 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1812 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1813 goto failed;
1814 }
1815
1816 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1817 if (!cmd) {
1818 err = -ENOMEM;
1819 goto failed;
1820 }
1821
1822 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1823 if (err < 0) {
1824 mgmt_pending_remove(cmd);
1825 goto failed;
1826 }
1827
1828failed:
1829 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001830 return err;
1831}
1832
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001833static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001834{
1835 struct mgmt_mode *cp = data;
1836 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001837 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001838 int err;
1839
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001840 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001841
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001842 status = mgmt_bredr_support(hdev);
1843 if (status)
1844 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1845
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001846 if (!lmp_ssp_capable(hdev))
1847 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1848 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001849
Johan Hedberga7e80f22013-01-09 16:05:19 +02001850 if (cp->val != 0x00 && cp->val != 0x01)
1851 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1852 MGMT_STATUS_INVALID_PARAMS);
1853
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001854 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001855
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001856 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001857 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001858
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001859 if (cp->val) {
1860 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1861 &hdev->dev_flags);
1862 } else {
1863 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1864 &hdev->dev_flags);
1865 if (!changed)
1866 changed = test_and_clear_bit(HCI_HS_ENABLED,
1867 &hdev->dev_flags);
1868 else
1869 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001870 }
1871
1872 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1873 if (err < 0)
1874 goto failed;
1875
1876 if (changed)
1877 err = new_settings(hdev, sk);
1878
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001879 goto failed;
1880 }
1881
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001882 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1883 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001884 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1885 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001886 goto failed;
1887 }
1888
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001889 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001890 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1891 goto failed;
1892 }
1893
1894 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1895 if (!cmd) {
1896 err = -ENOMEM;
1897 goto failed;
1898 }
1899
Johan Hedberg37699722014-06-24 14:00:27 +03001900 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1901 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1902 sizeof(cp->val), &cp->val);
1903
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001904 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001905 if (err < 0) {
1906 mgmt_pending_remove(cmd);
1907 goto failed;
1908 }
1909
1910failed:
1911 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001912 return err;
1913}
1914
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001915static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001916{
1917 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001918 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001919 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001920 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001921
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001922 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001923
Johan Hedberge6fe7982013-10-02 15:45:22 +03001924 status = mgmt_bredr_support(hdev);
1925 if (status)
1926 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001927
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001928 if (!lmp_ssp_capable(hdev))
1929 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1930 MGMT_STATUS_NOT_SUPPORTED);
1931
1932 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1933 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1934 MGMT_STATUS_REJECTED);
1935
Johan Hedberga7e80f22013-01-09 16:05:19 +02001936 if (cp->val != 0x00 && cp->val != 0x01)
1937 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1938 MGMT_STATUS_INVALID_PARAMS);
1939
Marcel Holtmannee392692013-10-01 22:59:23 -07001940 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001941
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001942 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001943 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001944 } else {
1945 if (hdev_is_powered(hdev)) {
1946 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1947 MGMT_STATUS_REJECTED);
1948 goto unlock;
1949 }
1950
Marcel Holtmannee392692013-10-01 22:59:23 -07001951 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001952 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001953
1954 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1955 if (err < 0)
1956 goto unlock;
1957
1958 if (changed)
1959 err = new_settings(hdev, sk);
1960
1961unlock:
1962 hci_dev_unlock(hdev);
1963 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001964}
1965
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001966static void le_enable_complete(struct hci_dev *hdev, u8 status)
1967{
1968 struct cmd_lookup match = { NULL, hdev };
1969
1970 if (status) {
1971 u8 mgmt_err = mgmt_status(status);
1972
1973 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1974 &mgmt_err);
1975 return;
1976 }
1977
1978 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1979
1980 new_settings(hdev, match.sk);
1981
1982 if (match.sk)
1983 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001984
1985 /* Make sure the controller has a good default for
1986 * advertising data. Restrict the update to when LE
1987 * has actually been enabled. During power on, the
1988 * update in powered_update_hci will take care of it.
1989 */
1990 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1991 struct hci_request req;
1992
1993 hci_dev_lock(hdev);
1994
1995 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001996 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001997 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001998 hci_req_run(&req, NULL);
1999
2000 hci_dev_unlock(hdev);
2001 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002002}
2003
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002004static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002005{
2006 struct mgmt_mode *cp = data;
2007 struct hci_cp_write_le_host_supported hci_cp;
2008 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002009 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002011 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002012
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002013 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002014
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002015 if (!lmp_le_capable(hdev))
2016 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2017 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002018
Johan Hedberga7e80f22013-01-09 16:05:19 +02002019 if (cp->val != 0x00 && cp->val != 0x01)
2020 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2021 MGMT_STATUS_INVALID_PARAMS);
2022
Johan Hedbergc73eee92013-04-19 18:35:21 +03002023 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002024 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002025 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2026 MGMT_STATUS_REJECTED);
2027
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002028 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002029
2030 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002031 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002032
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002033 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002034 bool changed = false;
2035
2036 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2037 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2038 changed = true;
2039 }
2040
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002041 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2042 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002043 changed = true;
2044 }
2045
Johan Hedberg06199cf2012-02-22 16:37:11 +02002046 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2047 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002048 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002049
2050 if (changed)
2051 err = new_settings(hdev, sk);
2052
Johan Hedberg1de028c2012-02-29 19:55:35 -08002053 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002054 }
2055
Johan Hedberg4375f102013-09-25 13:26:10 +03002056 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2057 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002058 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002059 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002060 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002061 }
2062
2063 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2064 if (!cmd) {
2065 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002066 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002067 }
2068
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002069 hci_req_init(&req, hdev);
2070
Johan Hedberg06199cf2012-02-22 16:37:11 +02002071 memset(&hci_cp, 0, sizeof(hci_cp));
2072
2073 if (val) {
2074 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002075 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002076 } else {
2077 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2078 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002079 }
2080
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002081 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2082 &hci_cp);
2083
2084 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302085 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002086 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002087
Johan Hedberg1de028c2012-02-29 19:55:35 -08002088unlock:
2089 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002090 return err;
2091}
2092
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002093/* This is a helper function to test for pending mgmt commands that can
2094 * cause CoD or EIR HCI commands. We can only allow one such pending
2095 * mgmt command at a time since otherwise we cannot easily track what
2096 * the current values are, will be, and based on that calculate if a new
2097 * HCI command needs to be sent and if yes with what value.
2098 */
2099static bool pending_eir_or_class(struct hci_dev *hdev)
2100{
2101 struct pending_cmd *cmd;
2102
2103 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2104 switch (cmd->opcode) {
2105 case MGMT_OP_ADD_UUID:
2106 case MGMT_OP_REMOVE_UUID:
2107 case MGMT_OP_SET_DEV_CLASS:
2108 case MGMT_OP_SET_POWERED:
2109 return true;
2110 }
2111 }
2112
2113 return false;
2114}
2115
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002116static const u8 bluetooth_base_uuid[] = {
2117 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2118 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2119};
2120
2121static u8 get_uuid_size(const u8 *uuid)
2122{
2123 u32 val;
2124
2125 if (memcmp(uuid, bluetooth_base_uuid, 12))
2126 return 128;
2127
2128 val = get_unaligned_le32(&uuid[12]);
2129 if (val > 0xffff)
2130 return 32;
2131
2132 return 16;
2133}
2134
Johan Hedberg92da6092013-03-15 17:06:55 -05002135static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2136{
2137 struct pending_cmd *cmd;
2138
2139 hci_dev_lock(hdev);
2140
2141 cmd = mgmt_pending_find(mgmt_op, hdev);
2142 if (!cmd)
2143 goto unlock;
2144
2145 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2146 hdev->dev_class, 3);
2147
2148 mgmt_pending_remove(cmd);
2149
2150unlock:
2151 hci_dev_unlock(hdev);
2152}
2153
2154static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2155{
2156 BT_DBG("status 0x%02x", status);
2157
2158 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2159}
2160
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002161static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002162{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002163 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002164 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002165 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002167 int err;
2168
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002169 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002170
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002171 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002172
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002173 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002174 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002175 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002176 goto failed;
2177 }
2178
Andre Guedes92c4c202012-06-07 19:05:44 -03002179 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002180 if (!uuid) {
2181 err = -ENOMEM;
2182 goto failed;
2183 }
2184
2185 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002186 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002187 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002188
Johan Hedbergde66aa62013-01-27 00:31:27 +02002189 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002190
Johan Hedberg890ea892013-03-15 17:06:52 -05002191 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002192
Johan Hedberg890ea892013-03-15 17:06:52 -05002193 update_class(&req);
2194 update_eir(&req);
2195
Johan Hedberg92da6092013-03-15 17:06:55 -05002196 err = hci_req_run(&req, add_uuid_complete);
2197 if (err < 0) {
2198 if (err != -ENODATA)
2199 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002200
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002201 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002202 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002203 goto failed;
2204 }
2205
2206 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002207 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002208 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002209 goto failed;
2210 }
2211
2212 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002213
2214failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002215 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002216 return err;
2217}
2218
Johan Hedberg24b78d02012-02-23 23:24:30 +02002219static bool enable_service_cache(struct hci_dev *hdev)
2220{
2221 if (!hdev_is_powered(hdev))
2222 return false;
2223
2224 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002225 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2226 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002227 return true;
2228 }
2229
2230 return false;
2231}
2232
Johan Hedberg92da6092013-03-15 17:06:55 -05002233static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2234{
2235 BT_DBG("status 0x%02x", status);
2236
2237 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2238}
2239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002241 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002242{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002243 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002244 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002245 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002246 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 -05002247 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002248 int err, found;
2249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002250 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002251
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002252 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002253
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002254 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002255 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002256 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002257 goto unlock;
2258 }
2259
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002260 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002261 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002262
Johan Hedberg24b78d02012-02-23 23:24:30 +02002263 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002264 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002265 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002266 goto unlock;
2267 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002268
Johan Hedberg9246a862012-02-23 21:33:16 +02002269 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002270 }
2271
2272 found = 0;
2273
Johan Hedberg056341c2013-01-27 00:31:30 +02002274 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002275 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2276 continue;
2277
2278 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002279 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002280 found++;
2281 }
2282
2283 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002284 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002285 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002286 goto unlock;
2287 }
2288
Johan Hedberg9246a862012-02-23 21:33:16 +02002289update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002290 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002291
Johan Hedberg890ea892013-03-15 17:06:52 -05002292 update_class(&req);
2293 update_eir(&req);
2294
Johan Hedberg92da6092013-03-15 17:06:55 -05002295 err = hci_req_run(&req, remove_uuid_complete);
2296 if (err < 0) {
2297 if (err != -ENODATA)
2298 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002299
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002300 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002301 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002302 goto unlock;
2303 }
2304
2305 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002306 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002307 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002308 goto unlock;
2309 }
2310
2311 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002312
2313unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002314 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002315 return err;
2316}
2317
Johan Hedberg92da6092013-03-15 17:06:55 -05002318static void set_class_complete(struct hci_dev *hdev, u8 status)
2319{
2320 BT_DBG("status 0x%02x", status);
2321
2322 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2323}
2324
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002325static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002326 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002327{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002328 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002329 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002330 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002331 int err;
2332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002333 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002334
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002335 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002336 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2337 MGMT_STATUS_NOT_SUPPORTED);
2338
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002339 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002340
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002341 if (pending_eir_or_class(hdev)) {
2342 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2343 MGMT_STATUS_BUSY);
2344 goto unlock;
2345 }
2346
2347 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2348 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2349 MGMT_STATUS_INVALID_PARAMS);
2350 goto unlock;
2351 }
2352
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002353 hdev->major_class = cp->major;
2354 hdev->minor_class = cp->minor;
2355
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002356 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002357 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002358 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002359 goto unlock;
2360 }
2361
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 hci_req_init(&req, hdev);
2363
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002364 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002365 hci_dev_unlock(hdev);
2366 cancel_delayed_work_sync(&hdev->service_cache);
2367 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002368 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002369 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002370
Johan Hedberg890ea892013-03-15 17:06:52 -05002371 update_class(&req);
2372
Johan Hedberg92da6092013-03-15 17:06:55 -05002373 err = hci_req_run(&req, set_class_complete);
2374 if (err < 0) {
2375 if (err != -ENODATA)
2376 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002377
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002378 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002379 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002380 goto unlock;
2381 }
2382
2383 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002384 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002385 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002386 goto unlock;
2387 }
2388
2389 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002390
Johan Hedbergb5235a62012-02-21 14:32:24 +02002391unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002392 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002393 return err;
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002397 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002399 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002400 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002401 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002402 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002403
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002404 BT_DBG("request for %s", hdev->name);
2405
2406 if (!lmp_bredr_capable(hdev))
2407 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2408 MGMT_STATUS_NOT_SUPPORTED);
2409
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002410 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002411
Johan Hedberg86742e12011-11-07 23:13:38 +02002412 expected_len = sizeof(*cp) + key_count *
2413 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002414 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002415 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002416 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002417 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002418 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002419 }
2420
Johan Hedberg4ae143012013-01-20 14:27:13 +02002421 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2422 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2423 MGMT_STATUS_INVALID_PARAMS);
2424
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002425 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002426 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002427
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002428 for (i = 0; i < key_count; i++) {
2429 struct mgmt_link_key_info *key = &cp->keys[i];
2430
Marcel Holtmann8e991132014-01-10 02:07:25 -08002431 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002432 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2433 MGMT_STATUS_INVALID_PARAMS);
2434 }
2435
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002436 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002437
2438 hci_link_keys_clear(hdev);
2439
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002440 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002441 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2442 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002443 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002444 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2445 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002446
2447 if (changed)
2448 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002449
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002450 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002451 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002452
Johan Hedberg58e92932014-06-24 14:00:26 +03002453 /* Always ignore debug keys and require a new pairing if
2454 * the user wants to use them.
2455 */
2456 if (key->type == HCI_LK_DEBUG_COMBINATION)
2457 continue;
2458
Johan Hedberg7652ff62014-06-24 13:15:49 +03002459 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2460 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002461 }
2462
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002463 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002464
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002465 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002466
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002467 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002468}
2469
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002470static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002471 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002472{
2473 struct mgmt_ev_device_unpaired ev;
2474
2475 bacpy(&ev.addr.bdaddr, bdaddr);
2476 ev.addr.type = addr_type;
2477
2478 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002479 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002480}
2481
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002482static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002483 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002484{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002485 struct mgmt_cp_unpair_device *cp = data;
2486 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002487 struct hci_cp_disconnect dc;
2488 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002489 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002490 int err;
2491
Johan Hedberga8a1d192011-11-10 15:54:38 +02002492 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002493 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2494 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002495
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002496 if (!bdaddr_type_is_valid(cp->addr.type))
2497 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2498 MGMT_STATUS_INVALID_PARAMS,
2499 &rp, sizeof(rp));
2500
Johan Hedberg118da702013-01-20 14:27:20 +02002501 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2502 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2503 MGMT_STATUS_INVALID_PARAMS,
2504 &rp, sizeof(rp));
2505
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002506 hci_dev_lock(hdev);
2507
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002508 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002509 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002510 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002511 goto unlock;
2512 }
2513
Johan Hedberge0b2b272014-02-18 17:14:31 +02002514 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002515 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002516 } else {
2517 u8 addr_type;
2518
2519 if (cp->addr.type == BDADDR_LE_PUBLIC)
2520 addr_type = ADDR_LE_DEV_PUBLIC;
2521 else
2522 addr_type = ADDR_LE_DEV_RANDOM;
2523
Johan Hedberga7ec7332014-02-18 17:14:35 +02002524 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2525
Andre Guedesa9b0a042014-02-26 20:21:52 -03002526 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2527
Johan Hedberge0b2b272014-02-18 17:14:31 +02002528 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2529 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002530
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002531 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002532 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002533 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002534 goto unlock;
2535 }
2536
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002537 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002538 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002539 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002540 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002541 else
2542 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002543 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002544 } else {
2545 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002546 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002547
Johan Hedberga8a1d192011-11-10 15:54:38 +02002548 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002549 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002551 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002552 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002553 }
2554
Johan Hedberg124f6e32012-02-09 13:50:12 +02002555 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002556 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002557 if (!cmd) {
2558 err = -ENOMEM;
2559 goto unlock;
2560 }
2561
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002562 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002563 dc.reason = 0x13; /* Remote User Terminated Connection */
2564 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2565 if (err < 0)
2566 mgmt_pending_remove(cmd);
2567
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002568unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002569 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002570 return err;
2571}
2572
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002573static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002574 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002576 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002577 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002578 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002579 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002580 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002581 int err;
2582
2583 BT_DBG("");
2584
Johan Hedberg06a63b12013-01-20 14:27:21 +02002585 memset(&rp, 0, sizeof(rp));
2586 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2587 rp.addr.type = cp->addr.type;
2588
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002589 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002590 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2591 MGMT_STATUS_INVALID_PARAMS,
2592 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002593
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002594 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002595
2596 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002597 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2598 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002599 goto failed;
2600 }
2601
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002602 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002603 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2604 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002605 goto failed;
2606 }
2607
Andre Guedes591f47f2012-04-24 21:02:49 -03002608 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002609 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2610 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002611 else
2612 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002613
Vishal Agarwalf9607272012-06-13 05:32:43 +05302614 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002615 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2616 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002617 goto failed;
2618 }
2619
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002620 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002621 if (!cmd) {
2622 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002623 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002624 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002625
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002626 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002627 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002628
2629 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2630 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002631 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002632
2633failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002634 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002635 return err;
2636}
2637
Andre Guedes57c14772012-04-24 21:02:50 -03002638static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002639{
2640 switch (link_type) {
2641 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002642 switch (addr_type) {
2643 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002644 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002645
Johan Hedberg48264f02011-11-09 13:58:58 +02002646 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002647 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002648 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002649 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002650
Johan Hedberg4c659c32011-11-07 23:13:39 +02002651 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002652 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002653 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002654 }
2655}
2656
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002657static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2658 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002659{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002660 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002661 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002662 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002663 int err;
2664 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002665
2666 BT_DBG("");
2667
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002668 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002669
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002670 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002671 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002672 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002673 goto unlock;
2674 }
2675
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002676 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002677 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2678 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002679 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002680 }
2681
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002682 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002683 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002684 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002685 err = -ENOMEM;
2686 goto unlock;
2687 }
2688
Johan Hedberg2784eb42011-01-21 13:56:35 +02002689 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002690 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002691 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2692 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002693 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002694 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002695 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002696 continue;
2697 i++;
2698 }
2699
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002700 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002701
Johan Hedberg4c659c32011-11-07 23:13:39 +02002702 /* Recalculate length in case of filtered SCO connections, etc */
2703 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002706 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002707
Johan Hedberga38528f2011-01-22 06:46:43 +02002708 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002709
2710unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002711 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002712 return err;
2713}
2714
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002715static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002716 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002717{
2718 struct pending_cmd *cmd;
2719 int err;
2720
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002721 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002722 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002723 if (!cmd)
2724 return -ENOMEM;
2725
Johan Hedbergd8457692012-02-17 14:24:57 +02002726 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002728 if (err < 0)
2729 mgmt_pending_remove(cmd);
2730
2731 return err;
2732}
2733
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002734static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002735 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002736{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002737 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002738 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002739 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002740 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002741 int err;
2742
2743 BT_DBG("");
2744
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002745 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002746
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002747 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002748 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002749 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002750 goto failed;
2751 }
2752
Johan Hedbergd8457692012-02-17 14:24:57 +02002753 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002754 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002755 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002756 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002757 goto failed;
2758 }
2759
2760 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002761 struct mgmt_cp_pin_code_neg_reply ncp;
2762
2763 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002764
2765 BT_ERR("PIN code is not 16 bytes long");
2766
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002767 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002768 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002769 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002770 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002771
2772 goto failed;
2773 }
2774
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002775 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002776 if (!cmd) {
2777 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002778 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002779 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002780
Johan Hedbergd8457692012-02-17 14:24:57 +02002781 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002782 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002783 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002784
2785 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2786 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002787 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002788
2789failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002790 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002791 return err;
2792}
2793
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002794static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2795 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002796{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002797 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002798
2799 BT_DBG("");
2800
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002801 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2802 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2803 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2804
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002805 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002806
2807 hdev->io_capability = cp->io_capability;
2808
2809 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002810 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002811
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002812 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002813
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002814 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2815 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002816}
2817
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002818static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002819{
2820 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002821 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002822
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002823 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002824 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2825 continue;
2826
Johan Hedberge9a416b2011-02-19 12:05:56 -03002827 if (cmd->user_data != conn)
2828 continue;
2829
2830 return cmd;
2831 }
2832
2833 return NULL;
2834}
2835
2836static void pairing_complete(struct pending_cmd *cmd, u8 status)
2837{
2838 struct mgmt_rp_pair_device rp;
2839 struct hci_conn *conn = cmd->user_data;
2840
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002841 bacpy(&rp.addr.bdaddr, &conn->dst);
2842 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002843
Johan Hedbergaee9b212012-02-18 15:07:59 +02002844 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002845 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002846
2847 /* So we don't get further callbacks for this connection */
2848 conn->connect_cfm_cb = NULL;
2849 conn->security_cfm_cb = NULL;
2850 conn->disconn_cfm_cb = NULL;
2851
David Herrmann76a68ba2013-04-06 20:28:37 +02002852 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002853
Johan Hedberga664b5b2011-02-19 12:06:02 -03002854 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002855}
2856
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002857void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2858{
2859 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2860 struct pending_cmd *cmd;
2861
2862 cmd = find_pairing(conn);
2863 if (cmd)
2864 pairing_complete(cmd, status);
2865}
2866
Johan Hedberge9a416b2011-02-19 12:05:56 -03002867static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2868{
2869 struct pending_cmd *cmd;
2870
2871 BT_DBG("status %u", status);
2872
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002873 cmd = find_pairing(conn);
2874 if (!cmd)
2875 BT_DBG("Unable to find a pending command");
2876 else
Johan Hedberge2113262012-02-18 15:20:03 +02002877 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002878}
2879
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002880static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302881{
2882 struct pending_cmd *cmd;
2883
2884 BT_DBG("status %u", status);
2885
2886 if (!status)
2887 return;
2888
2889 cmd = find_pairing(conn);
2890 if (!cmd)
2891 BT_DBG("Unable to find a pending command");
2892 else
2893 pairing_complete(cmd, mgmt_status(status));
2894}
2895
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002896static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002897 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002898{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002899 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002900 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002901 struct pending_cmd *cmd;
2902 u8 sec_level, auth_type;
2903 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002904 int err;
2905
2906 BT_DBG("");
2907
Szymon Jancf950a30e2013-01-18 12:48:07 +01002908 memset(&rp, 0, sizeof(rp));
2909 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2910 rp.addr.type = cp->addr.type;
2911
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002912 if (!bdaddr_type_is_valid(cp->addr.type))
2913 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2914 MGMT_STATUS_INVALID_PARAMS,
2915 &rp, sizeof(rp));
2916
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002917 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2918 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2919 MGMT_STATUS_INVALID_PARAMS,
2920 &rp, sizeof(rp));
2921
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002922 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002923
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002924 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002925 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2926 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002927 goto unlock;
2928 }
2929
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002930 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002931 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002932
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002933 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002934 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2935 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002936 } else {
2937 u8 addr_type;
2938
2939 /* Convert from L2CAP channel address type to HCI address type
2940 */
2941 if (cp->addr.type == BDADDR_LE_PUBLIC)
2942 addr_type = ADDR_LE_DEV_PUBLIC;
2943 else
2944 addr_type = ADDR_LE_DEV_RANDOM;
2945
2946 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002947 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002948 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002949
Ville Tervo30e76272011-02-22 16:10:53 -03002950 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002951 int status;
2952
2953 if (PTR_ERR(conn) == -EBUSY)
2954 status = MGMT_STATUS_BUSY;
2955 else
2956 status = MGMT_STATUS_CONNECT_FAILED;
2957
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002958 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002959 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002960 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002961 goto unlock;
2962 }
2963
2964 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002965 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002966 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002967 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002968 goto unlock;
2969 }
2970
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002971 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002972 if (!cmd) {
2973 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002974 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002975 goto unlock;
2976 }
2977
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002978 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002979 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002980 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002981 conn->security_cfm_cb = pairing_complete_cb;
2982 conn->disconn_cfm_cb = pairing_complete_cb;
2983 } else {
2984 conn->connect_cfm_cb = le_pairing_complete_cb;
2985 conn->security_cfm_cb = le_pairing_complete_cb;
2986 conn->disconn_cfm_cb = le_pairing_complete_cb;
2987 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002988
Johan Hedberge9a416b2011-02-19 12:05:56 -03002989 conn->io_capability = cp->io_cap;
2990 cmd->user_data = conn;
2991
2992 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002993 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002994 pairing_complete(cmd, 0);
2995
2996 err = 0;
2997
2998unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002999 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003000 return err;
3001}
3002
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3004 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003005{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003006 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003007 struct pending_cmd *cmd;
3008 struct hci_conn *conn;
3009 int err;
3010
3011 BT_DBG("");
3012
Johan Hedberg28424702012-02-02 04:02:29 +02003013 hci_dev_lock(hdev);
3014
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003015 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003016 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003017 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003018 goto unlock;
3019 }
3020
Johan Hedberg28424702012-02-02 04:02:29 +02003021 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3022 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003023 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003024 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003025 goto unlock;
3026 }
3027
3028 conn = cmd->user_data;
3029
3030 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003033 goto unlock;
3034 }
3035
3036 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3037
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003038 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003039 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003040unlock:
3041 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003042 return err;
3043}
3044
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003045static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003046 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003047 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003048{
Johan Hedberga5c29682011-02-19 12:05:57 -03003049 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003050 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003051 int err;
3052
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003053 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003054
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003055 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003056 err = cmd_complete(sk, hdev->id, mgmt_op,
3057 MGMT_STATUS_NOT_POWERED, addr,
3058 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003059 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003060 }
3061
Johan Hedberg1707c602013-03-15 17:07:15 -05003062 if (addr->type == BDADDR_BREDR)
3063 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003064 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003065 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003066
Johan Hedberg272d90d2012-02-09 15:26:12 +02003067 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003068 err = cmd_complete(sk, hdev->id, mgmt_op,
3069 MGMT_STATUS_NOT_CONNECTED, addr,
3070 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003071 goto done;
3072 }
3073
Johan Hedberg1707c602013-03-15 17:07:15 -05003074 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003075 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003076 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003077 err = cmd_complete(sk, hdev->id, mgmt_op,
3078 MGMT_STATUS_SUCCESS, addr,
3079 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003080 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003081 err = cmd_complete(sk, hdev->id, mgmt_op,
3082 MGMT_STATUS_FAILED, addr,
3083 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003084
Brian Gix47c15e22011-11-16 13:53:14 -08003085 goto done;
3086 }
3087
Johan Hedberg1707c602013-03-15 17:07:15 -05003088 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003089 if (!cmd) {
3090 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003091 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003092 }
3093
Brian Gix0df4c182011-11-16 13:53:13 -08003094 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003095 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3096 struct hci_cp_user_passkey_reply cp;
3097
Johan Hedberg1707c602013-03-15 17:07:15 -05003098 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003099 cp.passkey = passkey;
3100 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3101 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003102 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3103 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003104
Johan Hedberga664b5b2011-02-19 12:06:02 -03003105 if (err < 0)
3106 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003107
Brian Gix0df4c182011-11-16 13:53:13 -08003108done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003109 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003110 return err;
3111}
3112
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303113static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3114 void *data, u16 len)
3115{
3116 struct mgmt_cp_pin_code_neg_reply *cp = data;
3117
3118 BT_DBG("");
3119
Johan Hedberg1707c602013-03-15 17:07:15 -05003120 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303121 MGMT_OP_PIN_CODE_NEG_REPLY,
3122 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3123}
3124
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003125static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3126 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003127{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003128 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003129
3130 BT_DBG("");
3131
3132 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003133 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003134 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003135
Johan Hedberg1707c602013-03-15 17:07:15 -05003136 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003137 MGMT_OP_USER_CONFIRM_REPLY,
3138 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003139}
3140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003141static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003142 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003143{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003144 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003145
3146 BT_DBG("");
3147
Johan Hedberg1707c602013-03-15 17:07:15 -05003148 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3150 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003151}
3152
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003153static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3154 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003155{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003156 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003157
3158 BT_DBG("");
3159
Johan Hedberg1707c602013-03-15 17:07:15 -05003160 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003161 MGMT_OP_USER_PASSKEY_REPLY,
3162 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003163}
3164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003165static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003166 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003167{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003168 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003169
3170 BT_DBG("");
3171
Johan Hedberg1707c602013-03-15 17:07:15 -05003172 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003173 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3174 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003175}
3176
Johan Hedberg13928972013-03-15 17:07:00 -05003177static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003178{
Johan Hedberg13928972013-03-15 17:07:00 -05003179 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003180 struct hci_cp_write_local_name cp;
3181
Johan Hedberg13928972013-03-15 17:07:00 -05003182 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003183
Johan Hedberg890ea892013-03-15 17:06:52 -05003184 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003185}
3186
Johan Hedberg13928972013-03-15 17:07:00 -05003187static void set_name_complete(struct hci_dev *hdev, u8 status)
3188{
3189 struct mgmt_cp_set_local_name *cp;
3190 struct pending_cmd *cmd;
3191
3192 BT_DBG("status 0x%02x", status);
3193
3194 hci_dev_lock(hdev);
3195
3196 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3197 if (!cmd)
3198 goto unlock;
3199
3200 cp = cmd->param;
3201
3202 if (status)
3203 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3204 mgmt_status(status));
3205 else
3206 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3207 cp, sizeof(*cp));
3208
3209 mgmt_pending_remove(cmd);
3210
3211unlock:
3212 hci_dev_unlock(hdev);
3213}
3214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003217{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003218 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003219 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003220 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003221 int err;
3222
3223 BT_DBG("");
3224
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003225 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003226
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003227 /* If the old values are the same as the new ones just return a
3228 * direct command complete event.
3229 */
3230 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3231 !memcmp(hdev->short_name, cp->short_name,
3232 sizeof(hdev->short_name))) {
3233 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3234 data, len);
3235 goto failed;
3236 }
3237
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003238 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003239
Johan Hedbergb5235a62012-02-21 14:32:24 +02003240 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003241 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003242
3243 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003244 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003245 if (err < 0)
3246 goto failed;
3247
3248 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003249 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003250
Johan Hedbergb5235a62012-02-21 14:32:24 +02003251 goto failed;
3252 }
3253
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003254 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003255 if (!cmd) {
3256 err = -ENOMEM;
3257 goto failed;
3258 }
3259
Johan Hedberg13928972013-03-15 17:07:00 -05003260 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3261
Johan Hedberg890ea892013-03-15 17:06:52 -05003262 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003263
3264 if (lmp_bredr_capable(hdev)) {
3265 update_name(&req);
3266 update_eir(&req);
3267 }
3268
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003269 /* The name is stored in the scan response data and so
3270 * no need to udpate the advertising data here.
3271 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003272 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003273 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003274
Johan Hedberg13928972013-03-15 17:07:00 -05003275 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003276 if (err < 0)
3277 mgmt_pending_remove(cmd);
3278
3279failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003280 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003281 return err;
3282}
3283
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003284static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003286{
Szymon Jancc35938b2011-03-22 13:12:21 +01003287 struct pending_cmd *cmd;
3288 int err;
3289
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003290 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003291
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003292 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003293
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003294 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003295 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003297 goto unlock;
3298 }
3299
Andre Guedes9a1a1992012-07-24 15:03:48 -03003300 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003301 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003303 goto unlock;
3304 }
3305
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003306 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003307 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003308 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003309 goto unlock;
3310 }
3311
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003312 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003313 if (!cmd) {
3314 err = -ENOMEM;
3315 goto unlock;
3316 }
3317
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003318 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3319 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3320 0, NULL);
3321 else
3322 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3323
Szymon Jancc35938b2011-03-22 13:12:21 +01003324 if (err < 0)
3325 mgmt_pending_remove(cmd);
3326
3327unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003328 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003329 return err;
3330}
3331
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003332static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003333 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003334{
Szymon Janc2763eda2011-03-22 13:12:22 +01003335 int err;
3336
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003337 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003338
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003339 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003340
Marcel Holtmannec109112014-01-10 02:07:30 -08003341 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3342 struct mgmt_cp_add_remote_oob_data *cp = data;
3343 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003344
Marcel Holtmannec109112014-01-10 02:07:30 -08003345 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3346 cp->hash, cp->randomizer);
3347 if (err < 0)
3348 status = MGMT_STATUS_FAILED;
3349 else
3350 status = MGMT_STATUS_SUCCESS;
3351
3352 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3353 status, &cp->addr, sizeof(cp->addr));
3354 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3355 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3356 u8 status;
3357
3358 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3359 cp->hash192,
3360 cp->randomizer192,
3361 cp->hash256,
3362 cp->randomizer256);
3363 if (err < 0)
3364 status = MGMT_STATUS_FAILED;
3365 else
3366 status = MGMT_STATUS_SUCCESS;
3367
3368 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3369 status, &cp->addr, sizeof(cp->addr));
3370 } else {
3371 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3372 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3373 MGMT_STATUS_INVALID_PARAMS);
3374 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003375
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003376 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003377 return err;
3378}
3379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003380static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003381 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003382{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003383 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003384 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003385 int err;
3386
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003387 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003388
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003389 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003390
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003391 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003392 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003393 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003394 else
Szymon Janca6785be2012-12-13 15:11:21 +01003395 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003397 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003399
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003400 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003401 return err;
3402}
3403
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003404static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3405{
3406 struct pending_cmd *cmd;
3407 u8 type;
3408 int err;
3409
3410 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3411
3412 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3413 if (!cmd)
3414 return -ENOENT;
3415
3416 type = hdev->discovery.type;
3417
3418 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3419 &type, sizeof(type));
3420 mgmt_pending_remove(cmd);
3421
3422 return err;
3423}
3424
Andre Guedes7c307722013-04-30 15:29:28 -03003425static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3426{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003427 unsigned long timeout = 0;
3428
Andre Guedes7c307722013-04-30 15:29:28 -03003429 BT_DBG("status %d", status);
3430
3431 if (status) {
3432 hci_dev_lock(hdev);
3433 mgmt_start_discovery_failed(hdev, status);
3434 hci_dev_unlock(hdev);
3435 return;
3436 }
3437
3438 hci_dev_lock(hdev);
3439 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3440 hci_dev_unlock(hdev);
3441
3442 switch (hdev->discovery.type) {
3443 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003444 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003445 break;
3446
3447 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003448 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003449 break;
3450
3451 case DISCOV_TYPE_BREDR:
3452 break;
3453
3454 default:
3455 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3456 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003457
3458 if (!timeout)
3459 return;
3460
3461 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003462}
3463
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003464static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003465 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003466{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003467 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003468 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003469 struct hci_cp_le_set_scan_param param_cp;
3470 struct hci_cp_le_set_scan_enable enable_cp;
3471 struct hci_cp_inquiry inq_cp;
3472 struct hci_request req;
3473 /* General inquiry access code (GIAC) */
3474 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003475 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003476 int err;
3477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003478 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003479
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003480 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003481
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003482 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003483 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003484 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003485 goto failed;
3486 }
3487
Andre Guedes642be6c2012-03-21 00:03:37 -03003488 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3489 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3490 MGMT_STATUS_BUSY);
3491 goto failed;
3492 }
3493
Johan Hedbergff9ef572012-01-04 14:23:45 +02003494 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003495 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003496 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003497 goto failed;
3498 }
3499
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003500 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003501 if (!cmd) {
3502 err = -ENOMEM;
3503 goto failed;
3504 }
3505
Andre Guedes4aab14e2012-02-17 20:39:36 -03003506 hdev->discovery.type = cp->type;
3507
Andre Guedes7c307722013-04-30 15:29:28 -03003508 hci_req_init(&req, hdev);
3509
Andre Guedes4aab14e2012-02-17 20:39:36 -03003510 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003511 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003512 status = mgmt_bredr_support(hdev);
3513 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003514 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003515 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003516 mgmt_pending_remove(cmd);
3517 goto failed;
3518 }
3519
Andre Guedes7c307722013-04-30 15:29:28 -03003520 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3521 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3522 MGMT_STATUS_BUSY);
3523 mgmt_pending_remove(cmd);
3524 goto failed;
3525 }
3526
3527 hci_inquiry_cache_flush(hdev);
3528
3529 memset(&inq_cp, 0, sizeof(inq_cp));
3530 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003531 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003532 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003533 break;
3534
3535 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003536 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003537 status = mgmt_le_support(hdev);
3538 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003539 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003540 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003541 mgmt_pending_remove(cmd);
3542 goto failed;
3543 }
3544
Andre Guedes7c307722013-04-30 15:29:28 -03003545 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003546 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003547 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3548 MGMT_STATUS_NOT_SUPPORTED);
3549 mgmt_pending_remove(cmd);
3550 goto failed;
3551 }
3552
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003553 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003554 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3555 MGMT_STATUS_REJECTED);
3556 mgmt_pending_remove(cmd);
3557 goto failed;
3558 }
3559
Andre Guedesc54c3862014-02-26 20:21:50 -03003560 /* If controller is scanning, it means the background scanning
3561 * is running. Thus, we should temporarily stop it in order to
3562 * set the discovery scanning parameters.
3563 */
3564 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3565 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003566
3567 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003568
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003569 /* All active scans will be done with either a resolvable
3570 * private address (when privacy feature has been enabled)
3571 * or unresolvable private address.
3572 */
3573 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003574 if (err < 0) {
3575 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3576 MGMT_STATUS_FAILED);
3577 mgmt_pending_remove(cmd);
3578 goto failed;
3579 }
3580
Andre Guedes7c307722013-04-30 15:29:28 -03003581 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003582 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3583 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003584 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003585 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3586 &param_cp);
3587
3588 memset(&enable_cp, 0, sizeof(enable_cp));
3589 enable_cp.enable = LE_SCAN_ENABLE;
3590 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3591 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3592 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003593 break;
3594
Andre Guedesf39799f2012-02-17 20:39:35 -03003595 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003596 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3597 MGMT_STATUS_INVALID_PARAMS);
3598 mgmt_pending_remove(cmd);
3599 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003600 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003601
Andre Guedes7c307722013-04-30 15:29:28 -03003602 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003603 if (err < 0)
3604 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003605 else
3606 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003607
3608failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003609 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003610 return err;
3611}
3612
Andre Guedes1183fdc2013-04-30 15:29:35 -03003613static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3614{
3615 struct pending_cmd *cmd;
3616 int err;
3617
3618 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3619 if (!cmd)
3620 return -ENOENT;
3621
3622 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3623 &hdev->discovery.type, sizeof(hdev->discovery.type));
3624 mgmt_pending_remove(cmd);
3625
3626 return err;
3627}
3628
Andre Guedes0e05bba2013-04-30 15:29:33 -03003629static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3630{
3631 BT_DBG("status %d", status);
3632
3633 hci_dev_lock(hdev);
3634
3635 if (status) {
3636 mgmt_stop_discovery_failed(hdev, status);
3637 goto unlock;
3638 }
3639
3640 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3641
3642unlock:
3643 hci_dev_unlock(hdev);
3644}
3645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003646static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003647 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003648{
Johan Hedbergd9306502012-02-20 23:25:18 +02003649 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003650 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003651 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003652 int err;
3653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003654 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003655
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003656 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003657
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003658 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003659 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3661 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003662 goto unlock;
3663 }
3664
3665 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003666 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003667 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3668 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003669 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003670 }
3671
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003672 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003673 if (!cmd) {
3674 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003675 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003676 }
3677
Andre Guedes0e05bba2013-04-30 15:29:33 -03003678 hci_req_init(&req, hdev);
3679
Johan Hedberg21a60d32014-06-10 14:05:58 +03003680 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003681
Johan Hedberg21a60d32014-06-10 14:05:58 +03003682 err = hci_req_run(&req, stop_discovery_complete);
3683 if (!err) {
3684 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003685 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003686 }
3687
Johan Hedberg21a60d32014-06-10 14:05:58 +03003688 mgmt_pending_remove(cmd);
3689
3690 /* If no HCI commands were sent we're done */
3691 if (err == -ENODATA) {
3692 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3693 &mgmt_cp->type, sizeof(mgmt_cp->type));
3694 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3695 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003696
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003697unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003698 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003699 return err;
3700}
3701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003702static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003703 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003704{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003705 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003706 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003707 int err;
3708
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003709 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003710
Johan Hedberg561aafb2012-01-04 13:31:59 +02003711 hci_dev_lock(hdev);
3712
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003713 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003714 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3715 MGMT_STATUS_FAILED, &cp->addr,
3716 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003717 goto failed;
3718 }
3719
Johan Hedberga198e7b2012-02-17 14:27:06 +02003720 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003721 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003722 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3723 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3724 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003725 goto failed;
3726 }
3727
3728 if (cp->name_known) {
3729 e->name_state = NAME_KNOWN;
3730 list_del(&e->list);
3731 } else {
3732 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003733 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003734 }
3735
Johan Hedberge3846622013-01-09 15:29:33 +02003736 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3737 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003738
3739failed:
3740 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003741 return err;
3742}
3743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003744static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003745 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003746{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003747 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003748 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003749 int err;
3750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003751 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003752
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003753 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003754 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3755 MGMT_STATUS_INVALID_PARAMS,
3756 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003757
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003758 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003759
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003760 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003761 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003762 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003763 else
Szymon Janca6785be2012-12-13 15:11:21 +01003764 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003765
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003766 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003767 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003768
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003769 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003770
3771 return err;
3772}
3773
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003774static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003775 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003776{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003777 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003778 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003779 int err;
3780
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003781 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003782
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003783 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003784 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3785 MGMT_STATUS_INVALID_PARAMS,
3786 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003787
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003788 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003789
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003790 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003791 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003792 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003793 else
Szymon Janca6785be2012-12-13 15:11:21 +01003794 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003795
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003796 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003797 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003798
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003799 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003800
3801 return err;
3802}
3803
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003804static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3805 u16 len)
3806{
3807 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003808 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003809 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003810 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003811
3812 BT_DBG("%s", hdev->name);
3813
Szymon Jancc72d4b82012-03-16 16:02:57 +01003814 source = __le16_to_cpu(cp->source);
3815
3816 if (source > 0x0002)
3817 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3818 MGMT_STATUS_INVALID_PARAMS);
3819
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003820 hci_dev_lock(hdev);
3821
Szymon Jancc72d4b82012-03-16 16:02:57 +01003822 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003823 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3824 hdev->devid_product = __le16_to_cpu(cp->product);
3825 hdev->devid_version = __le16_to_cpu(cp->version);
3826
3827 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3828
Johan Hedberg890ea892013-03-15 17:06:52 -05003829 hci_req_init(&req, hdev);
3830 update_eir(&req);
3831 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003832
3833 hci_dev_unlock(hdev);
3834
3835 return err;
3836}
3837
Johan Hedberg4375f102013-09-25 13:26:10 +03003838static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3839{
3840 struct cmd_lookup match = { NULL, hdev };
3841
3842 if (status) {
3843 u8 mgmt_err = mgmt_status(status);
3844
3845 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3846 cmd_status_rsp, &mgmt_err);
3847 return;
3848 }
3849
3850 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3851 &match);
3852
3853 new_settings(hdev, match.sk);
3854
3855 if (match.sk)
3856 sock_put(match.sk);
3857}
3858
Marcel Holtmann21b51872013-10-10 09:47:53 -07003859static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3860 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003861{
3862 struct mgmt_mode *cp = data;
3863 struct pending_cmd *cmd;
3864 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003865 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003866 int err;
3867
3868 BT_DBG("request for %s", hdev->name);
3869
Johan Hedberge6fe7982013-10-02 15:45:22 +03003870 status = mgmt_le_support(hdev);
3871 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003872 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003873 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003874
3875 if (cp->val != 0x00 && cp->val != 0x01)
3876 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3877 MGMT_STATUS_INVALID_PARAMS);
3878
3879 hci_dev_lock(hdev);
3880
3881 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003882 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003883
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003884 /* The following conditions are ones which mean that we should
3885 * not do any HCI communication but directly send a mgmt
3886 * response to user space (after toggling the flag if
3887 * necessary).
3888 */
3889 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003890 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003891 bool changed = false;
3892
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003893 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3894 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003895 changed = true;
3896 }
3897
3898 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3899 if (err < 0)
3900 goto unlock;
3901
3902 if (changed)
3903 err = new_settings(hdev, sk);
3904
3905 goto unlock;
3906 }
3907
3908 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3909 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3910 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3911 MGMT_STATUS_BUSY);
3912 goto unlock;
3913 }
3914
3915 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3916 if (!cmd) {
3917 err = -ENOMEM;
3918 goto unlock;
3919 }
3920
3921 hci_req_init(&req, hdev);
3922
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003923 if (val)
3924 enable_advertising(&req);
3925 else
3926 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003927
3928 err = hci_req_run(&req, set_advertising_complete);
3929 if (err < 0)
3930 mgmt_pending_remove(cmd);
3931
3932unlock:
3933 hci_dev_unlock(hdev);
3934 return err;
3935}
3936
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003937static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3938 void *data, u16 len)
3939{
3940 struct mgmt_cp_set_static_address *cp = data;
3941 int err;
3942
3943 BT_DBG("%s", hdev->name);
3944
Marcel Holtmann62af4442013-10-02 22:10:32 -07003945 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003946 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003947 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003948
3949 if (hdev_is_powered(hdev))
3950 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3951 MGMT_STATUS_REJECTED);
3952
3953 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3954 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3955 return cmd_status(sk, hdev->id,
3956 MGMT_OP_SET_STATIC_ADDRESS,
3957 MGMT_STATUS_INVALID_PARAMS);
3958
3959 /* Two most significant bits shall be set */
3960 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3961 return cmd_status(sk, hdev->id,
3962 MGMT_OP_SET_STATIC_ADDRESS,
3963 MGMT_STATUS_INVALID_PARAMS);
3964 }
3965
3966 hci_dev_lock(hdev);
3967
3968 bacpy(&hdev->static_addr, &cp->bdaddr);
3969
3970 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3971
3972 hci_dev_unlock(hdev);
3973
3974 return err;
3975}
3976
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003977static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3978 void *data, u16 len)
3979{
3980 struct mgmt_cp_set_scan_params *cp = data;
3981 __u16 interval, window;
3982 int err;
3983
3984 BT_DBG("%s", hdev->name);
3985
3986 if (!lmp_le_capable(hdev))
3987 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3988 MGMT_STATUS_NOT_SUPPORTED);
3989
3990 interval = __le16_to_cpu(cp->interval);
3991
3992 if (interval < 0x0004 || interval > 0x4000)
3993 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3994 MGMT_STATUS_INVALID_PARAMS);
3995
3996 window = __le16_to_cpu(cp->window);
3997
3998 if (window < 0x0004 || window > 0x4000)
3999 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4000 MGMT_STATUS_INVALID_PARAMS);
4001
Marcel Holtmann899e1072013-10-14 09:55:32 -07004002 if (window > interval)
4003 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4004 MGMT_STATUS_INVALID_PARAMS);
4005
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004006 hci_dev_lock(hdev);
4007
4008 hdev->le_scan_interval = interval;
4009 hdev->le_scan_window = window;
4010
4011 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4012
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004013 /* If background scan is running, restart it so new parameters are
4014 * loaded.
4015 */
4016 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4017 hdev->discovery.state == DISCOVERY_STOPPED) {
4018 struct hci_request req;
4019
4020 hci_req_init(&req, hdev);
4021
4022 hci_req_add_le_scan_disable(&req);
4023 hci_req_add_le_passive_scan(&req);
4024
4025 hci_req_run(&req, NULL);
4026 }
4027
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004028 hci_dev_unlock(hdev);
4029
4030 return err;
4031}
4032
Johan Hedberg33e38b32013-03-15 17:07:05 -05004033static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4034{
4035 struct pending_cmd *cmd;
4036
4037 BT_DBG("status 0x%02x", status);
4038
4039 hci_dev_lock(hdev);
4040
4041 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4042 if (!cmd)
4043 goto unlock;
4044
4045 if (status) {
4046 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4047 mgmt_status(status));
4048 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004049 struct mgmt_mode *cp = cmd->param;
4050
4051 if (cp->val)
4052 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4053 else
4054 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4055
Johan Hedberg33e38b32013-03-15 17:07:05 -05004056 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4057 new_settings(hdev, cmd->sk);
4058 }
4059
4060 mgmt_pending_remove(cmd);
4061
4062unlock:
4063 hci_dev_unlock(hdev);
4064}
4065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004066static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004067 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004068{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004069 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004070 struct pending_cmd *cmd;
4071 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004072 int err;
4073
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004074 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004075
Johan Hedberg56f87902013-10-02 13:43:13 +03004076 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4077 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004078 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4079 MGMT_STATUS_NOT_SUPPORTED);
4080
Johan Hedberga7e80f22013-01-09 16:05:19 +02004081 if (cp->val != 0x00 && cp->val != 0x01)
4082 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4083 MGMT_STATUS_INVALID_PARAMS);
4084
Johan Hedberg5400c042012-02-21 16:40:33 +02004085 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004086 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004087 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004088
4089 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004090 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004091 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004092
4093 hci_dev_lock(hdev);
4094
Johan Hedberg05cbf292013-03-15 17:07:07 -05004095 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4096 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4097 MGMT_STATUS_BUSY);
4098 goto unlock;
4099 }
4100
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004101 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4102 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4103 hdev);
4104 goto unlock;
4105 }
4106
Johan Hedberg33e38b32013-03-15 17:07:05 -05004107 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4108 data, len);
4109 if (!cmd) {
4110 err = -ENOMEM;
4111 goto unlock;
4112 }
4113
4114 hci_req_init(&req, hdev);
4115
Johan Hedberg406d7802013-03-15 17:07:09 -05004116 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004117
4118 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004119 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004120 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004121 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004122 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004123 }
4124
Johan Hedberg33e38b32013-03-15 17:07:05 -05004125unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004126 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004127
Antti Julkuf6422ec2011-06-22 13:11:56 +03004128 return err;
4129}
4130
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004131static void set_bredr_scan(struct hci_request *req)
4132{
4133 struct hci_dev *hdev = req->hdev;
4134 u8 scan = 0;
4135
4136 /* Ensure that fast connectable is disabled. This function will
4137 * not do anything if the page scan parameters are already what
4138 * they should be.
4139 */
4140 write_fast_connectable(req, false);
4141
4142 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4143 scan |= SCAN_PAGE;
4144 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4145 scan |= SCAN_INQUIRY;
4146
4147 if (scan)
4148 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4149}
4150
Johan Hedberg0663ca22013-10-02 13:43:14 +03004151static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4152{
4153 struct pending_cmd *cmd;
4154
4155 BT_DBG("status 0x%02x", status);
4156
4157 hci_dev_lock(hdev);
4158
4159 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4160 if (!cmd)
4161 goto unlock;
4162
4163 if (status) {
4164 u8 mgmt_err = mgmt_status(status);
4165
4166 /* We need to restore the flag if related HCI commands
4167 * failed.
4168 */
4169 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4170
4171 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4172 } else {
4173 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4174 new_settings(hdev, cmd->sk);
4175 }
4176
4177 mgmt_pending_remove(cmd);
4178
4179unlock:
4180 hci_dev_unlock(hdev);
4181}
4182
4183static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4184{
4185 struct mgmt_mode *cp = data;
4186 struct pending_cmd *cmd;
4187 struct hci_request req;
4188 int err;
4189
4190 BT_DBG("request for %s", hdev->name);
4191
4192 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4193 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4194 MGMT_STATUS_NOT_SUPPORTED);
4195
4196 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4197 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4198 MGMT_STATUS_REJECTED);
4199
4200 if (cp->val != 0x00 && cp->val != 0x01)
4201 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4202 MGMT_STATUS_INVALID_PARAMS);
4203
4204 hci_dev_lock(hdev);
4205
4206 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4207 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4208 goto unlock;
4209 }
4210
4211 if (!hdev_is_powered(hdev)) {
4212 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004213 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4214 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4215 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4216 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4217 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4218 }
4219
4220 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4221
4222 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4223 if (err < 0)
4224 goto unlock;
4225
4226 err = new_settings(hdev, sk);
4227 goto unlock;
4228 }
4229
4230 /* Reject disabling when powered on */
4231 if (!cp->val) {
4232 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4233 MGMT_STATUS_REJECTED);
4234 goto unlock;
4235 }
4236
4237 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4238 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4239 MGMT_STATUS_BUSY);
4240 goto unlock;
4241 }
4242
4243 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4244 if (!cmd) {
4245 err = -ENOMEM;
4246 goto unlock;
4247 }
4248
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004249 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004250 * generates the correct flags.
4251 */
4252 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4253
4254 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004255
4256 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4257 set_bredr_scan(&req);
4258
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004259 /* Since only the advertising data flags will change, there
4260 * is no need to update the scan response data.
4261 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004262 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004263
Johan Hedberg0663ca22013-10-02 13:43:14 +03004264 err = hci_req_run(&req, set_bredr_complete);
4265 if (err < 0)
4266 mgmt_pending_remove(cmd);
4267
4268unlock:
4269 hci_dev_unlock(hdev);
4270 return err;
4271}
4272
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004273static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4274 void *data, u16 len)
4275{
4276 struct mgmt_mode *cp = data;
4277 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004278 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004279 int err;
4280
4281 BT_DBG("request for %s", hdev->name);
4282
4283 status = mgmt_bredr_support(hdev);
4284 if (status)
4285 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4286 status);
4287
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004288 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004289 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004290 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4291 MGMT_STATUS_NOT_SUPPORTED);
4292
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004293 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004294 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4295 MGMT_STATUS_INVALID_PARAMS);
4296
4297 hci_dev_lock(hdev);
4298
4299 if (!hdev_is_powered(hdev)) {
4300 bool changed;
4301
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004302 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004303 changed = !test_and_set_bit(HCI_SC_ENABLED,
4304 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004305 if (cp->val == 0x02)
4306 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4307 else
4308 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4309 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004310 changed = test_and_clear_bit(HCI_SC_ENABLED,
4311 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004312 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4313 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004314
4315 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4316 if (err < 0)
4317 goto failed;
4318
4319 if (changed)
4320 err = new_settings(hdev, sk);
4321
4322 goto failed;
4323 }
4324
4325 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4326 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4327 MGMT_STATUS_BUSY);
4328 goto failed;
4329 }
4330
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004331 val = !!cp->val;
4332
4333 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4334 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004335 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4336 goto failed;
4337 }
4338
4339 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4340 if (!cmd) {
4341 err = -ENOMEM;
4342 goto failed;
4343 }
4344
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004345 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004346 if (err < 0) {
4347 mgmt_pending_remove(cmd);
4348 goto failed;
4349 }
4350
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004351 if (cp->val == 0x02)
4352 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4353 else
4354 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4355
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004356failed:
4357 hci_dev_unlock(hdev);
4358 return err;
4359}
4360
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004361static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4362 void *data, u16 len)
4363{
4364 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004365 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004366 int err;
4367
4368 BT_DBG("request for %s", hdev->name);
4369
Johan Hedbergb97109792014-06-24 14:00:28 +03004370 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004371 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4372 MGMT_STATUS_INVALID_PARAMS);
4373
4374 hci_dev_lock(hdev);
4375
4376 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004377 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4378 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004379 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004380 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4381 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004382
Johan Hedbergb97109792014-06-24 14:00:28 +03004383 if (cp->val == 0x02)
4384 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4385 &hdev->dev_flags);
4386 else
4387 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4388 &hdev->dev_flags);
4389
4390 if (hdev_is_powered(hdev) && use_changed &&
4391 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4392 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4393 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4394 sizeof(mode), &mode);
4395 }
4396
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004397 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4398 if (err < 0)
4399 goto unlock;
4400
4401 if (changed)
4402 err = new_settings(hdev, sk);
4403
4404unlock:
4405 hci_dev_unlock(hdev);
4406 return err;
4407}
4408
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004409static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4410 u16 len)
4411{
4412 struct mgmt_cp_set_privacy *cp = cp_data;
4413 bool changed;
4414 int err;
4415
4416 BT_DBG("request for %s", hdev->name);
4417
4418 if (!lmp_le_capable(hdev))
4419 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4420 MGMT_STATUS_NOT_SUPPORTED);
4421
4422 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4423 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4424 MGMT_STATUS_INVALID_PARAMS);
4425
4426 if (hdev_is_powered(hdev))
4427 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4428 MGMT_STATUS_REJECTED);
4429
4430 hci_dev_lock(hdev);
4431
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004432 /* If user space supports this command it is also expected to
4433 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4434 */
4435 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4436
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004437 if (cp->privacy) {
4438 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4439 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4440 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4441 } else {
4442 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4443 memset(hdev->irk, 0, sizeof(hdev->irk));
4444 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4445 }
4446
4447 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4448 if (err < 0)
4449 goto unlock;
4450
4451 if (changed)
4452 err = new_settings(hdev, sk);
4453
4454unlock:
4455 hci_dev_unlock(hdev);
4456 return err;
4457}
4458
Johan Hedberg41edf162014-02-18 10:19:35 +02004459static bool irk_is_valid(struct mgmt_irk_info *irk)
4460{
4461 switch (irk->addr.type) {
4462 case BDADDR_LE_PUBLIC:
4463 return true;
4464
4465 case BDADDR_LE_RANDOM:
4466 /* Two most significant bits shall be set */
4467 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4468 return false;
4469 return true;
4470 }
4471
4472 return false;
4473}
4474
4475static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4476 u16 len)
4477{
4478 struct mgmt_cp_load_irks *cp = cp_data;
4479 u16 irk_count, expected_len;
4480 int i, err;
4481
4482 BT_DBG("request for %s", hdev->name);
4483
4484 if (!lmp_le_capable(hdev))
4485 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4486 MGMT_STATUS_NOT_SUPPORTED);
4487
4488 irk_count = __le16_to_cpu(cp->irk_count);
4489
4490 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4491 if (expected_len != len) {
4492 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004493 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004494 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4495 MGMT_STATUS_INVALID_PARAMS);
4496 }
4497
4498 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4499
4500 for (i = 0; i < irk_count; i++) {
4501 struct mgmt_irk_info *key = &cp->irks[i];
4502
4503 if (!irk_is_valid(key))
4504 return cmd_status(sk, hdev->id,
4505 MGMT_OP_LOAD_IRKS,
4506 MGMT_STATUS_INVALID_PARAMS);
4507 }
4508
4509 hci_dev_lock(hdev);
4510
4511 hci_smp_irks_clear(hdev);
4512
4513 for (i = 0; i < irk_count; i++) {
4514 struct mgmt_irk_info *irk = &cp->irks[i];
4515 u8 addr_type;
4516
4517 if (irk->addr.type == BDADDR_LE_PUBLIC)
4518 addr_type = ADDR_LE_DEV_PUBLIC;
4519 else
4520 addr_type = ADDR_LE_DEV_RANDOM;
4521
4522 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4523 BDADDR_ANY);
4524 }
4525
4526 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4527
4528 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4529
4530 hci_dev_unlock(hdev);
4531
4532 return err;
4533}
4534
Johan Hedberg3f706b72013-01-20 14:27:16 +02004535static bool ltk_is_valid(struct mgmt_ltk_info *key)
4536{
4537 if (key->master != 0x00 && key->master != 0x01)
4538 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004539
4540 switch (key->addr.type) {
4541 case BDADDR_LE_PUBLIC:
4542 return true;
4543
4544 case BDADDR_LE_RANDOM:
4545 /* Two most significant bits shall be set */
4546 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4547 return false;
4548 return true;
4549 }
4550
4551 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004552}
4553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004554static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004555 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004556{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004557 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4558 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004559 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004560
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004561 BT_DBG("request for %s", hdev->name);
4562
4563 if (!lmp_le_capable(hdev))
4564 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4565 MGMT_STATUS_NOT_SUPPORTED);
4566
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004567 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004568
4569 expected_len = sizeof(*cp) + key_count *
4570 sizeof(struct mgmt_ltk_info);
4571 if (expected_len != len) {
4572 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004573 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004574 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004575 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004576 }
4577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004578 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004579
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004580 for (i = 0; i < key_count; i++) {
4581 struct mgmt_ltk_info *key = &cp->keys[i];
4582
Johan Hedberg3f706b72013-01-20 14:27:16 +02004583 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004584 return cmd_status(sk, hdev->id,
4585 MGMT_OP_LOAD_LONG_TERM_KEYS,
4586 MGMT_STATUS_INVALID_PARAMS);
4587 }
4588
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004589 hci_dev_lock(hdev);
4590
4591 hci_smp_ltks_clear(hdev);
4592
4593 for (i = 0; i < key_count; i++) {
4594 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004595 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004596
4597 if (key->addr.type == BDADDR_LE_PUBLIC)
4598 addr_type = ADDR_LE_DEV_PUBLIC;
4599 else
4600 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004601
4602 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004603 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004604 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004605 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004606
Johan Hedberg61b43352014-05-29 19:36:53 +03004607 switch (key->type) {
4608 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004609 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004610 break;
4611 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004612 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004613 break;
4614 default:
4615 continue;
4616 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004617
Johan Hedberg35d70272014-02-19 14:57:47 +02004618 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004619 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004620 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004621 }
4622
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004623 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4624 NULL, 0);
4625
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004626 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004627
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004628 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004629}
4630
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004631struct cmd_conn_lookup {
4632 struct hci_conn *conn;
4633 bool valid_tx_power;
4634 u8 mgmt_status;
4635};
4636
4637static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4638{
4639 struct cmd_conn_lookup *match = data;
4640 struct mgmt_cp_get_conn_info *cp;
4641 struct mgmt_rp_get_conn_info rp;
4642 struct hci_conn *conn = cmd->user_data;
4643
4644 if (conn != match->conn)
4645 return;
4646
4647 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4648
4649 memset(&rp, 0, sizeof(rp));
4650 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4651 rp.addr.type = cp->addr.type;
4652
4653 if (!match->mgmt_status) {
4654 rp.rssi = conn->rssi;
4655
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004656 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004657 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004658 rp.max_tx_power = conn->max_tx_power;
4659 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004660 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004661 rp.max_tx_power = HCI_TX_POWER_INVALID;
4662 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004663 }
4664
4665 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4666 match->mgmt_status, &rp, sizeof(rp));
4667
4668 hci_conn_drop(conn);
4669
4670 mgmt_pending_remove(cmd);
4671}
4672
4673static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4674{
4675 struct hci_cp_read_rssi *cp;
4676 struct hci_conn *conn;
4677 struct cmd_conn_lookup match;
4678 u16 handle;
4679
4680 BT_DBG("status 0x%02x", status);
4681
4682 hci_dev_lock(hdev);
4683
4684 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004685 * otherwise we assume it's not valid. At the moment we assume that
4686 * either both or none of current and max values are valid to keep code
4687 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004688 */
4689 match.valid_tx_power = !status;
4690
4691 /* Commands sent in request are either Read RSSI or Read Transmit Power
4692 * Level so we check which one was last sent to retrieve connection
4693 * handle. Both commands have handle as first parameter so it's safe to
4694 * cast data on the same command struct.
4695 *
4696 * First command sent is always Read RSSI and we fail only if it fails.
4697 * In other case we simply override error to indicate success as we
4698 * already remembered if TX power value is actually valid.
4699 */
4700 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4701 if (!cp) {
4702 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4703 status = 0;
4704 }
4705
4706 if (!cp) {
4707 BT_ERR("invalid sent_cmd in response");
4708 goto unlock;
4709 }
4710
4711 handle = __le16_to_cpu(cp->handle);
4712 conn = hci_conn_hash_lookup_handle(hdev, handle);
4713 if (!conn) {
4714 BT_ERR("unknown handle (%d) in response", handle);
4715 goto unlock;
4716 }
4717
4718 match.conn = conn;
4719 match.mgmt_status = mgmt_status(status);
4720
4721 /* Cache refresh is complete, now reply for mgmt request for given
4722 * connection only.
4723 */
4724 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4725 get_conn_info_complete, &match);
4726
4727unlock:
4728 hci_dev_unlock(hdev);
4729}
4730
4731static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4732 u16 len)
4733{
4734 struct mgmt_cp_get_conn_info *cp = data;
4735 struct mgmt_rp_get_conn_info rp;
4736 struct hci_conn *conn;
4737 unsigned long conn_info_age;
4738 int err = 0;
4739
4740 BT_DBG("%s", hdev->name);
4741
4742 memset(&rp, 0, sizeof(rp));
4743 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4744 rp.addr.type = cp->addr.type;
4745
4746 if (!bdaddr_type_is_valid(cp->addr.type))
4747 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4748 MGMT_STATUS_INVALID_PARAMS,
4749 &rp, sizeof(rp));
4750
4751 hci_dev_lock(hdev);
4752
4753 if (!hdev_is_powered(hdev)) {
4754 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4755 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4756 goto unlock;
4757 }
4758
4759 if (cp->addr.type == BDADDR_BREDR)
4760 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4761 &cp->addr.bdaddr);
4762 else
4763 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4764
4765 if (!conn || conn->state != BT_CONNECTED) {
4766 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4767 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4768 goto unlock;
4769 }
4770
4771 /* To avoid client trying to guess when to poll again for information we
4772 * calculate conn info age as random value between min/max set in hdev.
4773 */
4774 conn_info_age = hdev->conn_info_min_age +
4775 prandom_u32_max(hdev->conn_info_max_age -
4776 hdev->conn_info_min_age);
4777
4778 /* Query controller to refresh cached values if they are too old or were
4779 * never read.
4780 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004781 if (time_after(jiffies, conn->conn_info_timestamp +
4782 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004783 !conn->conn_info_timestamp) {
4784 struct hci_request req;
4785 struct hci_cp_read_tx_power req_txp_cp;
4786 struct hci_cp_read_rssi req_rssi_cp;
4787 struct pending_cmd *cmd;
4788
4789 hci_req_init(&req, hdev);
4790 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4791 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4792 &req_rssi_cp);
4793
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004794 /* For LE links TX power does not change thus we don't need to
4795 * query for it once value is known.
4796 */
4797 if (!bdaddr_type_is_le(cp->addr.type) ||
4798 conn->tx_power == HCI_TX_POWER_INVALID) {
4799 req_txp_cp.handle = cpu_to_le16(conn->handle);
4800 req_txp_cp.type = 0x00;
4801 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4802 sizeof(req_txp_cp), &req_txp_cp);
4803 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004804
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004805 /* Max TX power needs to be read only once per connection */
4806 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4807 req_txp_cp.handle = cpu_to_le16(conn->handle);
4808 req_txp_cp.type = 0x01;
4809 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4810 sizeof(req_txp_cp), &req_txp_cp);
4811 }
4812
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004813 err = hci_req_run(&req, conn_info_refresh_complete);
4814 if (err < 0)
4815 goto unlock;
4816
4817 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4818 data, len);
4819 if (!cmd) {
4820 err = -ENOMEM;
4821 goto unlock;
4822 }
4823
4824 hci_conn_hold(conn);
4825 cmd->user_data = conn;
4826
4827 conn->conn_info_timestamp = jiffies;
4828 } else {
4829 /* Cache is valid, just reply with values cached in hci_conn */
4830 rp.rssi = conn->rssi;
4831 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004832 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004833
4834 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4835 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4836 }
4837
4838unlock:
4839 hci_dev_unlock(hdev);
4840 return err;
4841}
4842
Johan Hedberg95868422014-06-28 17:54:07 +03004843static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4844{
4845 struct mgmt_cp_get_clock_info *cp;
4846 struct mgmt_rp_get_clock_info rp;
4847 struct hci_cp_read_clock *hci_cp;
4848 struct pending_cmd *cmd;
4849 struct hci_conn *conn;
4850
4851 BT_DBG("%s status %u", hdev->name, status);
4852
4853 hci_dev_lock(hdev);
4854
4855 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4856 if (!hci_cp)
4857 goto unlock;
4858
4859 if (hci_cp->which) {
4860 u16 handle = __le16_to_cpu(hci_cp->handle);
4861 conn = hci_conn_hash_lookup_handle(hdev, handle);
4862 } else {
4863 conn = NULL;
4864 }
4865
4866 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4867 if (!cmd)
4868 goto unlock;
4869
4870 cp = cmd->param;
4871
4872 memset(&rp, 0, sizeof(rp));
4873 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4874
4875 if (status)
4876 goto send_rsp;
4877
4878 rp.local_clock = cpu_to_le32(hdev->clock);
4879
4880 if (conn) {
4881 rp.piconet_clock = cpu_to_le32(conn->clock);
4882 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4883 }
4884
4885send_rsp:
4886 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4887 &rp, sizeof(rp));
4888 mgmt_pending_remove(cmd);
4889 if (conn)
4890 hci_conn_drop(conn);
4891
4892unlock:
4893 hci_dev_unlock(hdev);
4894}
4895
4896static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4897 u16 len)
4898{
4899 struct mgmt_cp_get_clock_info *cp = data;
4900 struct mgmt_rp_get_clock_info rp;
4901 struct hci_cp_read_clock hci_cp;
4902 struct pending_cmd *cmd;
4903 struct hci_request req;
4904 struct hci_conn *conn;
4905 int err;
4906
4907 BT_DBG("%s", hdev->name);
4908
4909 memset(&rp, 0, sizeof(rp));
4910 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4911 rp.addr.type = cp->addr.type;
4912
4913 if (cp->addr.type != BDADDR_BREDR)
4914 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4915 MGMT_STATUS_INVALID_PARAMS,
4916 &rp, sizeof(rp));
4917
4918 hci_dev_lock(hdev);
4919
4920 if (!hdev_is_powered(hdev)) {
4921 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
4922 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4923 goto unlock;
4924 }
4925
4926 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
4927 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4928 &cp->addr.bdaddr);
4929 if (!conn || conn->state != BT_CONNECTED) {
4930 err = cmd_complete(sk, hdev->id,
4931 MGMT_OP_GET_CLOCK_INFO,
4932 MGMT_STATUS_NOT_CONNECTED,
4933 &rp, sizeof(rp));
4934 goto unlock;
4935 }
4936 } else {
4937 conn = NULL;
4938 }
4939
4940 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
4941 if (!cmd) {
4942 err = -ENOMEM;
4943 goto unlock;
4944 }
4945
4946 hci_req_init(&req, hdev);
4947
4948 memset(&hci_cp, 0, sizeof(hci_cp));
4949 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4950
4951 if (conn) {
4952 hci_conn_hold(conn);
4953 cmd->user_data = conn;
4954
4955 hci_cp.handle = cpu_to_le16(conn->handle);
4956 hci_cp.which = 0x01; /* Piconet clock */
4957 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
4958 }
4959
4960 err = hci_req_run(&req, get_clock_info_complete);
4961 if (err < 0)
4962 mgmt_pending_remove(cmd);
4963
4964unlock:
4965 hci_dev_unlock(hdev);
4966 return err;
4967}
4968
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004969static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004970 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4971 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004972 bool var_len;
4973 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004974} mgmt_handlers[] = {
4975 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004976 { read_version, false, MGMT_READ_VERSION_SIZE },
4977 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4978 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4979 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4980 { set_powered, false, MGMT_SETTING_SIZE },
4981 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4982 { set_connectable, false, MGMT_SETTING_SIZE },
4983 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4984 { set_pairable, false, MGMT_SETTING_SIZE },
4985 { set_link_security, false, MGMT_SETTING_SIZE },
4986 { set_ssp, false, MGMT_SETTING_SIZE },
4987 { set_hs, false, MGMT_SETTING_SIZE },
4988 { set_le, false, MGMT_SETTING_SIZE },
4989 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4990 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4991 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4992 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4993 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4994 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4995 { disconnect, false, MGMT_DISCONNECT_SIZE },
4996 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4997 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4998 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4999 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5000 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5001 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5002 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5003 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5004 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5005 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5006 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5007 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005008 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005009 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5010 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5011 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5012 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5013 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5014 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005015 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005016 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005017 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005018 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005019 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005020 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005021 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005022 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005023 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005024 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005025 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005026};
5027
5028
Johan Hedberg03811012010-12-08 00:21:06 +02005029int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5030{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005031 void *buf;
5032 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005033 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005034 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005035 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005036 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005037 int err;
5038
5039 BT_DBG("got %zu bytes", msglen);
5040
5041 if (msglen < sizeof(*hdr))
5042 return -EINVAL;
5043
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005044 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005045 if (!buf)
5046 return -ENOMEM;
5047
5048 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5049 err = -EFAULT;
5050 goto done;
5051 }
5052
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005053 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005054 opcode = __le16_to_cpu(hdr->opcode);
5055 index = __le16_to_cpu(hdr->index);
5056 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005057
5058 if (len != msglen - sizeof(*hdr)) {
5059 err = -EINVAL;
5060 goto done;
5061 }
5062
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005063 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005064 hdev = hci_dev_get(index);
5065 if (!hdev) {
5066 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005067 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005068 goto done;
5069 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005070
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005071 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannfee746b2014-06-29 12:13:05 +02005072 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) ||
5073 test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005074 err = cmd_status(sk, index, opcode,
5075 MGMT_STATUS_INVALID_INDEX);
5076 goto done;
5077 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005078 }
5079
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005080 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005081 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005082 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005083 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005084 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005085 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005086 }
5087
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005088 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005089 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005090 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005091 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005092 goto done;
5093 }
5094
Johan Hedbergbe22b542012-03-01 22:24:41 +02005095 handler = &mgmt_handlers[opcode];
5096
5097 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005098 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005099 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005100 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005101 goto done;
5102 }
5103
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005104 if (hdev)
5105 mgmt_init_hdev(sk, hdev);
5106
5107 cp = buf + sizeof(*hdr);
5108
Johan Hedbergbe22b542012-03-01 22:24:41 +02005109 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005110 if (err < 0)
5111 goto done;
5112
Johan Hedberg03811012010-12-08 00:21:06 +02005113 err = msglen;
5114
5115done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005116 if (hdev)
5117 hci_dev_put(hdev);
5118
Johan Hedberg03811012010-12-08 00:21:06 +02005119 kfree(buf);
5120 return err;
5121}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005122
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005123void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005124{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005125 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005126 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005127
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005128 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005129}
5130
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005131void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005132{
Johan Hedberg5f159032012-03-02 03:13:19 +02005133 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005134
Marcel Holtmann1514b892013-10-06 08:25:01 -07005135 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005136 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005137
Johan Hedberg744cf192011-11-08 20:40:14 +02005138 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005139
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005140 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005141}
5142
Andre Guedes6046dc32014-02-26 20:21:51 -03005143/* This function requires the caller holds hdev->lock */
5144static void restart_le_auto_conns(struct hci_dev *hdev)
5145{
5146 struct hci_conn_params *p;
5147
5148 list_for_each_entry(p, &hdev->le_conn_params, list) {
5149 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
5150 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
5151 }
5152}
5153
Johan Hedberg229ab392013-03-15 17:06:53 -05005154static void powered_complete(struct hci_dev *hdev, u8 status)
5155{
5156 struct cmd_lookup match = { NULL, hdev };
5157
5158 BT_DBG("status 0x%02x", status);
5159
5160 hci_dev_lock(hdev);
5161
Andre Guedes6046dc32014-02-26 20:21:51 -03005162 restart_le_auto_conns(hdev);
5163
Johan Hedberg229ab392013-03-15 17:06:53 -05005164 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5165
5166 new_settings(hdev, match.sk);
5167
5168 hci_dev_unlock(hdev);
5169
5170 if (match.sk)
5171 sock_put(match.sk);
5172}
5173
Johan Hedberg70da6242013-03-15 17:06:51 -05005174static int powered_update_hci(struct hci_dev *hdev)
5175{
Johan Hedberg890ea892013-03-15 17:06:52 -05005176 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005177 u8 link_sec;
5178
Johan Hedberg890ea892013-03-15 17:06:52 -05005179 hci_req_init(&req, hdev);
5180
Johan Hedberg70da6242013-03-15 17:06:51 -05005181 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5182 !lmp_host_ssp_capable(hdev)) {
5183 u8 ssp = 1;
5184
Johan Hedberg890ea892013-03-15 17:06:52 -05005185 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005186 }
5187
Johan Hedbergc73eee92013-04-19 18:35:21 +03005188 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5189 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005190 struct hci_cp_write_le_host_supported cp;
5191
5192 cp.le = 1;
5193 cp.simul = lmp_le_br_capable(hdev);
5194
5195 /* Check first if we already have the right
5196 * host state (host features set)
5197 */
5198 if (cp.le != lmp_host_le_capable(hdev) ||
5199 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005200 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5201 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005202 }
5203
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005204 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005205 /* Make sure the controller has a good default for
5206 * advertising data. This also applies to the case
5207 * where BR/EDR was toggled during the AUTO_OFF phase.
5208 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005209 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005210 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005211 update_scan_rsp_data(&req);
5212 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005213
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005214 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5215 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005216 }
5217
Johan Hedberg70da6242013-03-15 17:06:51 -05005218 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5219 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005220 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5221 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005222
5223 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005224 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5225 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005226 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005227 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005228 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005229 }
5230
Johan Hedberg229ab392013-03-15 17:06:53 -05005231 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005232}
5233
Johan Hedberg744cf192011-11-08 20:40:14 +02005234int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005235{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005236 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005237 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5238 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005239 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005240
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005241 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5242 return 0;
5243
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005244 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005245 if (powered_update_hci(hdev) == 0)
5246 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005247
Johan Hedberg229ab392013-03-15 17:06:53 -05005248 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5249 &match);
5250 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005251 }
5252
Johan Hedberg229ab392013-03-15 17:06:53 -05005253 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5254 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5255
5256 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5257 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5258 zero_cod, sizeof(zero_cod), NULL);
5259
5260new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005261 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005262
5263 if (match.sk)
5264 sock_put(match.sk);
5265
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005266 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005267}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005268
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005269void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005270{
5271 struct pending_cmd *cmd;
5272 u8 status;
5273
5274 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5275 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005276 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005277
5278 if (err == -ERFKILL)
5279 status = MGMT_STATUS_RFKILLED;
5280 else
5281 status = MGMT_STATUS_FAILED;
5282
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005283 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005284
5285 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005286}
5287
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005288void mgmt_discoverable_timeout(struct hci_dev *hdev)
5289{
5290 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005291
5292 hci_dev_lock(hdev);
5293
5294 /* When discoverable timeout triggers, then just make sure
5295 * the limited discoverable flag is cleared. Even in the case
5296 * of a timeout triggered from general discoverable, it is
5297 * safe to unconditionally clear the flag.
5298 */
5299 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005300 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005301
5302 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005303 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5304 u8 scan = SCAN_PAGE;
5305 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5306 sizeof(scan), &scan);
5307 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005308 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005309 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005310 hci_req_run(&req, NULL);
5311
5312 hdev->discov_timeout = 0;
5313
Johan Hedberg9a43e252013-10-20 19:00:07 +03005314 new_settings(hdev, NULL);
5315
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005316 hci_dev_unlock(hdev);
5317}
5318
Marcel Holtmann86a75642013-10-15 06:33:54 -07005319void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005320{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005321 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005322
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005323 /* Nothing needed here if there's a pending command since that
5324 * commands request completion callback takes care of everything
5325 * necessary.
5326 */
5327 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005328 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005329
Johan Hedbergbd107992014-02-24 14:52:19 +02005330 /* Powering off may clear the scan mode - don't let that interfere */
5331 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5332 return;
5333
Johan Hedberg9a43e252013-10-20 19:00:07 +03005334 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005335 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005336 } else {
5337 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005338 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005339 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005340
Johan Hedberg9a43e252013-10-20 19:00:07 +03005341 if (changed) {
5342 struct hci_request req;
5343
5344 /* In case this change in discoverable was triggered by
5345 * a disabling of connectable there could be a need to
5346 * update the advertising flags.
5347 */
5348 hci_req_init(&req, hdev);
5349 update_adv_data(&req);
5350 hci_req_run(&req, NULL);
5351
Marcel Holtmann86a75642013-10-15 06:33:54 -07005352 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005353 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005354}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005355
Marcel Holtmanna3309162013-10-15 06:33:55 -07005356void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005357{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005358 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005359
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005360 /* Nothing needed here if there's a pending command since that
5361 * commands request completion callback takes care of everything
5362 * necessary.
5363 */
5364 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005365 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005366
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005367 /* Powering off may clear the scan mode - don't let that interfere */
5368 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5369 return;
5370
Marcel Holtmanna3309162013-10-15 06:33:55 -07005371 if (connectable)
5372 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5373 else
5374 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005375
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005376 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005377 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005378}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005379
Johan Hedberg778b2352014-02-24 14:52:17 +02005380void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5381{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005382 /* Powering off may stop advertising - don't let that interfere */
5383 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5384 return;
5385
Johan Hedberg778b2352014-02-24 14:52:17 +02005386 if (advertising)
5387 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5388 else
5389 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5390}
5391
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005392void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005393{
Johan Hedbergca69b792011-11-11 18:10:00 +02005394 u8 mgmt_err = mgmt_status(status);
5395
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005396 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005397 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005398 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005399
5400 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005401 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005402 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005403}
5404
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005405void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5406 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005407{
Johan Hedberg86742e12011-11-07 23:13:38 +02005408 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005409
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005410 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005411
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005412 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005413 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005414 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005415 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005416 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005417 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005418
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005419 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005420}
Johan Hedbergf7520542011-01-20 12:34:39 +02005421
Johan Hedbergd7b25452014-05-23 13:19:53 +03005422static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5423{
5424 if (ltk->authenticated)
5425 return MGMT_LTK_AUTHENTICATED;
5426
5427 return MGMT_LTK_UNAUTHENTICATED;
5428}
5429
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005430void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005431{
5432 struct mgmt_ev_new_long_term_key ev;
5433
5434 memset(&ev, 0, sizeof(ev));
5435
Marcel Holtmann5192d302014-02-19 17:11:58 -08005436 /* Devices using resolvable or non-resolvable random addresses
5437 * without providing an indentity resolving key don't require
5438 * to store long term keys. Their addresses will change the
5439 * next time around.
5440 *
5441 * Only when a remote device provides an identity address
5442 * make sure the long term key is stored. If the remote
5443 * identity is known, the long term keys are internally
5444 * mapped to the identity address. So allow static random
5445 * and public addresses here.
5446 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005447 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5448 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5449 ev.store_hint = 0x00;
5450 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005451 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005452
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005453 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005454 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005455 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005456 ev.key.enc_size = key->enc_size;
5457 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005458 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005459
Johan Hedberg2ceba532014-06-16 19:25:16 +03005460 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005461 ev.key.master = 1;
5462
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005463 memcpy(ev.key.val, key->val, sizeof(key->val));
5464
Marcel Holtmann083368f2013-10-15 14:26:29 -07005465 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005466}
5467
Johan Hedberg95fbac82014-02-19 15:18:31 +02005468void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5469{
5470 struct mgmt_ev_new_irk ev;
5471
5472 memset(&ev, 0, sizeof(ev));
5473
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005474 /* For identity resolving keys from devices that are already
5475 * using a public address or static random address, do not
5476 * ask for storing this key. The identity resolving key really
5477 * is only mandatory for devices using resovlable random
5478 * addresses.
5479 *
5480 * Storing all identity resolving keys has the downside that
5481 * they will be also loaded on next boot of they system. More
5482 * identity resolving keys, means more time during scanning is
5483 * needed to actually resolve these addresses.
5484 */
5485 if (bacmp(&irk->rpa, BDADDR_ANY))
5486 ev.store_hint = 0x01;
5487 else
5488 ev.store_hint = 0x00;
5489
Johan Hedberg95fbac82014-02-19 15:18:31 +02005490 bacpy(&ev.rpa, &irk->rpa);
5491 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5492 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5493 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5494
5495 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5496}
5497
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005498void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5499 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005500{
5501 struct mgmt_ev_new_csrk ev;
5502
5503 memset(&ev, 0, sizeof(ev));
5504
5505 /* Devices using resolvable or non-resolvable random addresses
5506 * without providing an indentity resolving key don't require
5507 * to store signature resolving keys. Their addresses will change
5508 * the next time around.
5509 *
5510 * Only when a remote device provides an identity address
5511 * make sure the signature resolving key is stored. So allow
5512 * static random and public addresses here.
5513 */
5514 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5515 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5516 ev.store_hint = 0x00;
5517 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005518 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005519
5520 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5521 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5522 ev.key.master = csrk->master;
5523 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5524
5525 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5526}
5527
Marcel Holtmann94933992013-10-15 10:26:39 -07005528static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5529 u8 data_len)
5530{
5531 eir[eir_len++] = sizeof(type) + data_len;
5532 eir[eir_len++] = type;
5533 memcpy(&eir[eir_len], data, data_len);
5534 eir_len += data_len;
5535
5536 return eir_len;
5537}
5538
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005539void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5540 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5541 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005542{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005543 char buf[512];
5544 struct mgmt_ev_device_connected *ev = (void *) buf;
5545 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005546
Johan Hedbergb644ba32012-01-17 21:48:47 +02005547 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005548 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005549
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005550 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005551
Johan Hedbergb644ba32012-01-17 21:48:47 +02005552 if (name_len > 0)
5553 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005554 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005555
5556 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005557 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005558 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005559
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005560 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005561
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005562 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5563 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005564}
5565
Johan Hedberg8962ee72011-01-20 12:40:27 +02005566static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5567{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005568 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005569 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005570 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005571
Johan Hedberg88c3df12012-02-09 14:27:38 +02005572 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5573 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005574
Johan Hedbergaee9b212012-02-18 15:07:59 +02005575 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005576 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005577
5578 *sk = cmd->sk;
5579 sock_hold(*sk);
5580
Johan Hedberga664b5b2011-02-19 12:06:02 -03005581 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005582}
5583
Johan Hedberg124f6e32012-02-09 13:50:12 +02005584static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005585{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005586 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005587 struct mgmt_cp_unpair_device *cp = cmd->param;
5588 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005589
5590 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005591 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5592 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005593
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005594 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5595
Johan Hedbergaee9b212012-02-18 15:07:59 +02005596 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005597
5598 mgmt_pending_remove(cmd);
5599}
5600
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005601void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005602 u8 link_type, u8 addr_type, u8 reason,
5603 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005604{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005605 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005606 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005607 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005608
Johan Hedberg8b064a32014-02-24 14:52:22 +02005609 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5610 if (power_off) {
5611 struct mgmt_mode *cp = power_off->param;
5612
5613 /* The connection is still in hci_conn_hash so test for 1
5614 * instead of 0 to know if this is the last one.
5615 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005616 if (!cp->val && hci_conn_count(hdev) == 1) {
5617 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005618 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005619 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005620 }
5621
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005622 if (!mgmt_connected)
5623 return;
5624
Andre Guedes57eb7762013-10-30 19:01:41 -03005625 if (link_type != ACL_LINK && link_type != LE_LINK)
5626 return;
5627
Johan Hedberg744cf192011-11-08 20:40:14 +02005628 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005629
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005630 bacpy(&ev.addr.bdaddr, bdaddr);
5631 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5632 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005633
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005634 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005635
5636 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005637 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005638
Johan Hedberg124f6e32012-02-09 13:50:12 +02005639 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005640 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005641}
5642
Marcel Holtmann78929242013-10-06 23:55:47 -07005643void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5644 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005645{
Andre Guedes3655bba2013-10-30 19:01:40 -03005646 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5647 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005648 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005649 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005650
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005651 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5652 hdev);
5653
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005654 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005655 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005656 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005657
Andre Guedes3655bba2013-10-30 19:01:40 -03005658 cp = cmd->param;
5659
5660 if (bacmp(bdaddr, &cp->addr.bdaddr))
5661 return;
5662
5663 if (cp->addr.type != bdaddr_type)
5664 return;
5665
Johan Hedberg88c3df12012-02-09 14:27:38 +02005666 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005667 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005668
Marcel Holtmann78929242013-10-06 23:55:47 -07005669 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5670 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005671
Johan Hedberga664b5b2011-02-19 12:06:02 -03005672 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005673}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005674
Marcel Holtmann445608d2013-10-06 23:55:48 -07005675void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5676 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005677{
5678 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005679 struct pending_cmd *power_off;
5680
5681 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5682 if (power_off) {
5683 struct mgmt_mode *cp = power_off->param;
5684
5685 /* The connection is still in hci_conn_hash so test for 1
5686 * instead of 0 to know if this is the last one.
5687 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005688 if (!cp->val && hci_conn_count(hdev) == 1) {
5689 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005690 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005691 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005692 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005693
Johan Hedberg4c659c32011-11-07 23:13:39 +02005694 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005695 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005696 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005697
Marcel Holtmann445608d2013-10-06 23:55:48 -07005698 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005699}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005700
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005701void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005702{
5703 struct mgmt_ev_pin_code_request ev;
5704
Johan Hedbergd8457692012-02-17 14:24:57 +02005705 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005706 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005707 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005708
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005709 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005710}
5711
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005712void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5713 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005714{
5715 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005716 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005717
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005718 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005719 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005720 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005721
Johan Hedbergd8457692012-02-17 14:24:57 +02005722 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005723 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005724
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005725 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5726 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005727
Johan Hedberga664b5b2011-02-19 12:06:02 -03005728 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005729}
5730
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005731void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5732 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005733{
5734 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005735 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005736
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005737 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005738 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005739 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005740
Johan Hedbergd8457692012-02-17 14:24:57 +02005741 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005742 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005743
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005744 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5745 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005746
Johan Hedberga664b5b2011-02-19 12:06:02 -03005747 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005748}
Johan Hedberga5c29682011-02-19 12:05:57 -03005749
Johan Hedberg744cf192011-11-08 20:40:14 +02005750int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005751 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005752 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005753{
5754 struct mgmt_ev_user_confirm_request ev;
5755
Johan Hedberg744cf192011-11-08 20:40:14 +02005756 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005757
Johan Hedberg272d90d2012-02-09 15:26:12 +02005758 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005759 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005760 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005761 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005762
Johan Hedberg744cf192011-11-08 20:40:14 +02005763 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005764 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005765}
5766
Johan Hedberg272d90d2012-02-09 15:26:12 +02005767int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005768 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005769{
5770 struct mgmt_ev_user_passkey_request ev;
5771
5772 BT_DBG("%s", hdev->name);
5773
Johan Hedberg272d90d2012-02-09 15:26:12 +02005774 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005775 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005776
5777 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005778 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005779}
5780
Brian Gix0df4c182011-11-16 13:53:13 -08005781static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005782 u8 link_type, u8 addr_type, u8 status,
5783 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005784{
5785 struct pending_cmd *cmd;
5786 struct mgmt_rp_user_confirm_reply rp;
5787 int err;
5788
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005789 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005790 if (!cmd)
5791 return -ENOENT;
5792
Johan Hedberg272d90d2012-02-09 15:26:12 +02005793 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005794 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02005795 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005796 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005797
Johan Hedberga664b5b2011-02-19 12:06:02 -03005798 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005799
5800 return err;
5801}
5802
Johan Hedberg744cf192011-11-08 20:40:14 +02005803int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005804 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005805{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005806 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005807 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005808}
5809
Johan Hedberg272d90d2012-02-09 15:26:12 +02005810int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005811 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005812{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005813 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005814 status,
5815 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005816}
Johan Hedberg2a611692011-02-19 12:06:00 -03005817
Brian Gix604086b2011-11-23 08:28:33 -08005818int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005819 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005820{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005821 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005822 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005823}
5824
Johan Hedberg272d90d2012-02-09 15:26:12 +02005825int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005826 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005827{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005828 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005829 status,
5830 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005831}
5832
Johan Hedberg92a25252012-09-06 18:39:26 +03005833int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5834 u8 link_type, u8 addr_type, u32 passkey,
5835 u8 entered)
5836{
5837 struct mgmt_ev_passkey_notify ev;
5838
5839 BT_DBG("%s", hdev->name);
5840
5841 bacpy(&ev.addr.bdaddr, bdaddr);
5842 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5843 ev.passkey = __cpu_to_le32(passkey);
5844 ev.entered = entered;
5845
5846 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5847}
5848
Marcel Holtmanne5460992013-10-15 14:26:23 -07005849void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5850 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005851{
5852 struct mgmt_ev_auth_failed ev;
5853
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005854 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005855 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005856 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005857
Marcel Holtmanne5460992013-10-15 14:26:23 -07005858 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005859}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005860
Marcel Holtmann464996a2013-10-15 14:26:24 -07005861void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005862{
5863 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005864 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005865
5866 if (status) {
5867 u8 mgmt_err = mgmt_status(status);
5868 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005869 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005870 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005871 }
5872
Marcel Holtmann464996a2013-10-15 14:26:24 -07005873 if (test_bit(HCI_AUTH, &hdev->flags))
5874 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5875 &hdev->dev_flags);
5876 else
5877 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5878 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005879
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005880 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005881 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005882
Johan Hedberg47990ea2012-02-22 11:58:37 +02005883 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005884 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005885
5886 if (match.sk)
5887 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005888}
5889
Johan Hedberg890ea892013-03-15 17:06:52 -05005890static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005891{
Johan Hedberg890ea892013-03-15 17:06:52 -05005892 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005893 struct hci_cp_write_eir cp;
5894
Johan Hedberg976eb202012-10-24 21:12:01 +03005895 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005896 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005897
Johan Hedbergc80da272012-02-22 15:38:48 +02005898 memset(hdev->eir, 0, sizeof(hdev->eir));
5899
Johan Hedbergcacaf522012-02-21 00:52:42 +02005900 memset(&cp, 0, sizeof(cp));
5901
Johan Hedberg890ea892013-03-15 17:06:52 -05005902 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005903}
5904
Marcel Holtmann3e248562013-10-15 14:26:25 -07005905void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005906{
5907 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005908 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005909 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005910
5911 if (status) {
5912 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005913
5914 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005915 &hdev->dev_flags)) {
5916 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005917 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005918 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005919
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005920 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5921 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005922 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005923 }
5924
5925 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005926 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005927 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005928 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5929 if (!changed)
5930 changed = test_and_clear_bit(HCI_HS_ENABLED,
5931 &hdev->dev_flags);
5932 else
5933 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005934 }
5935
5936 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5937
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005938 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005939 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005940
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005941 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005942 sock_put(match.sk);
5943
Johan Hedberg890ea892013-03-15 17:06:52 -05005944 hci_req_init(&req, hdev);
5945
Johan Hedberg37699722014-06-24 14:00:27 +03005946 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
5947 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
5948 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
5949 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05005950 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005951 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05005952 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03005953 }
Johan Hedberg890ea892013-03-15 17:06:52 -05005954
5955 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005956}
5957
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005958void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5959{
5960 struct cmd_lookup match = { NULL, hdev };
5961 bool changed = false;
5962
5963 if (status) {
5964 u8 mgmt_err = mgmt_status(status);
5965
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005966 if (enable) {
5967 if (test_and_clear_bit(HCI_SC_ENABLED,
5968 &hdev->dev_flags))
5969 new_settings(hdev, NULL);
5970 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5971 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005972
5973 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5974 cmd_status_rsp, &mgmt_err);
5975 return;
5976 }
5977
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005978 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005979 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005980 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005981 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005982 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5983 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005984
5985 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5986 settings_rsp, &match);
5987
5988 if (changed)
5989 new_settings(hdev, match.sk);
5990
5991 if (match.sk)
5992 sock_put(match.sk);
5993}
5994
Johan Hedberg92da6092013-03-15 17:06:55 -05005995static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005996{
5997 struct cmd_lookup *match = data;
5998
Johan Hedberg90e70452012-02-23 23:09:40 +02005999 if (match->sk == NULL) {
6000 match->sk = cmd->sk;
6001 sock_hold(match->sk);
6002 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006003}
6004
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006005void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6006 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006007{
Johan Hedberg90e70452012-02-23 23:09:40 +02006008 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006009
Johan Hedberg92da6092013-03-15 17:06:55 -05006010 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6011 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6012 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006013
6014 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006015 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6016 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006017
6018 if (match.sk)
6019 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006020}
6021
Marcel Holtmann7667da32013-10-15 14:26:27 -07006022void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006023{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006024 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006025 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006026
Johan Hedberg13928972013-03-15 17:07:00 -05006027 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006028 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006029
6030 memset(&ev, 0, sizeof(ev));
6031 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006032 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006033
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006034 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006035 if (!cmd) {
6036 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006037
Johan Hedberg13928972013-03-15 17:07:00 -05006038 /* If this is a HCI command related to powering on the
6039 * HCI dev don't send any mgmt signals.
6040 */
6041 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006042 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006043 }
6044
Marcel Holtmann7667da32013-10-15 14:26:27 -07006045 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6046 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006047}
Szymon Jancc35938b2011-03-22 13:12:21 +01006048
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006049void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6050 u8 *randomizer192, u8 *hash256,
6051 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006052{
6053 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006054
Johan Hedberg744cf192011-11-08 20:40:14 +02006055 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006056
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006057 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006058 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006059 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006060
6061 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006062 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6063 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006064 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006065 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6066 hash256 && randomizer256) {
6067 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006068
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006069 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6070 memcpy(rp.randomizer192, randomizer192,
6071 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006072
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006073 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6074 memcpy(rp.randomizer256, randomizer256,
6075 sizeof(rp.randomizer256));
6076
6077 cmd_complete(cmd->sk, hdev->id,
6078 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6079 &rp, sizeof(rp));
6080 } else {
6081 struct mgmt_rp_read_local_oob_data rp;
6082
6083 memcpy(rp.hash, hash192, sizeof(rp.hash));
6084 memcpy(rp.randomizer, randomizer192,
6085 sizeof(rp.randomizer));
6086
6087 cmd_complete(cmd->sk, hdev->id,
6088 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6089 &rp, sizeof(rp));
6090 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006091 }
6092
6093 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006094}
Johan Hedberge17acd42011-03-30 23:57:16 +03006095
Marcel Holtmann901801b2013-10-06 23:55:51 -07006096void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02006097 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
6098 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006099 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006100{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006101 char buf[512];
6102 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006103 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006104 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006105
Andre Guedes12602d02013-04-30 15:29:40 -03006106 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006107 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006108
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006109 /* Make sure that the buffer is big enough. The 5 extra bytes
6110 * are for the potential CoD field.
6111 */
6112 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006113 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006114
Johan Hedberg1dc06092012-01-15 21:01:23 +02006115 memset(buf, 0, sizeof(buf));
6116
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006117 irk = hci_get_irk(hdev, bdaddr, addr_type);
6118 if (irk) {
6119 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6120 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6121 } else {
6122 bacpy(&ev->addr.bdaddr, bdaddr);
6123 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6124 }
6125
Johan Hedberge319d2e2012-01-15 19:51:59 +02006126 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02006127 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006128 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02006129 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07006130 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03006131
Johan Hedberg1dc06092012-01-15 21:01:23 +02006132 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006133 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006134
Johan Hedberg1dc06092012-01-15 21:01:23 +02006135 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6136 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006137 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006138
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006139 if (scan_rsp_len > 0)
6140 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6141
6142 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6143 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006144
Marcel Holtmann901801b2013-10-06 23:55:51 -07006145 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006146}
Johan Hedberga88a9652011-03-30 13:18:12 +03006147
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006148void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6149 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006150{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006151 struct mgmt_ev_device_found *ev;
6152 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6153 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006154
Johan Hedbergb644ba32012-01-17 21:48:47 +02006155 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006156
Johan Hedbergb644ba32012-01-17 21:48:47 +02006157 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006158
Johan Hedbergb644ba32012-01-17 21:48:47 +02006159 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006160 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006161 ev->rssi = rssi;
6162
6163 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006164 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006165
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006166 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006167
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006168 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006169}
Johan Hedberg314b2382011-04-27 10:29:57 -04006170
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006171void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006172{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006173 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006174 struct pending_cmd *cmd;
6175
Andre Guedes343fb142011-11-22 17:14:19 -03006176 BT_DBG("%s discovering %u", hdev->name, discovering);
6177
Johan Hedberg164a6e72011-11-01 17:06:44 +02006178 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006179 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006180 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006181 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006182
6183 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006184 u8 type = hdev->discovery.type;
6185
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006186 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6187 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006188 mgmt_pending_remove(cmd);
6189 }
6190
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006191 memset(&ev, 0, sizeof(ev));
6192 ev.type = hdev->discovery.type;
6193 ev.discovering = discovering;
6194
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006195 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006196}
Antti Julku5e762442011-08-25 16:48:02 +03006197
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006198int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006199{
6200 struct pending_cmd *cmd;
6201 struct mgmt_ev_device_blocked ev;
6202
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006203 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006204
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006205 bacpy(&ev.addr.bdaddr, bdaddr);
6206 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006207
Johan Hedberg744cf192011-11-08 20:40:14 +02006208 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006209 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006210}
6211
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006212int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006213{
6214 struct pending_cmd *cmd;
6215 struct mgmt_ev_device_unblocked ev;
6216
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006217 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006218
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006219 bacpy(&ev.addr.bdaddr, bdaddr);
6220 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006221
Johan Hedberg744cf192011-11-08 20:40:14 +02006222 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006223 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006224}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006225
6226static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6227{
6228 BT_DBG("%s status %u", hdev->name, status);
6229
6230 /* Clear the advertising mgmt setting if we failed to re-enable it */
6231 if (status) {
6232 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006233 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006234 }
6235}
6236
6237void mgmt_reenable_advertising(struct hci_dev *hdev)
6238{
6239 struct hci_request req;
6240
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006241 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006242 return;
6243
6244 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6245 return;
6246
6247 hci_req_init(&req, hdev);
6248 enable_advertising(&req);
6249
6250 /* If this fails we have no option but to let user space know
6251 * that we've disabled advertising.
6252 */
6253 if (hci_req_run(&req, adv_enable_complete) < 0) {
6254 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006255 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006256 }
6257}