blob: 664dbc4eccbe46a5938b05b4ca552f0ffc6e08b9 [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>
32#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070033
34#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020035
Johan Hedberg2da9c552012-02-17 14:39:28 +020036#define MGMT_VERSION 1
Marcel Holtmannb75cf9c2014-05-09 04:18:42 -070037#define MGMT_REVISION 6
Johan Hedberg02d98122010-12-13 21:07:04 +020038
Johan Hedberge70bb2e2012-02-13 16:59:33 +020039static const u16 mgmt_commands[] = {
40 MGMT_OP_READ_INDEX_LIST,
41 MGMT_OP_READ_INFO,
42 MGMT_OP_SET_POWERED,
43 MGMT_OP_SET_DISCOVERABLE,
44 MGMT_OP_SET_CONNECTABLE,
45 MGMT_OP_SET_FAST_CONNECTABLE,
46 MGMT_OP_SET_PAIRABLE,
47 MGMT_OP_SET_LINK_SECURITY,
48 MGMT_OP_SET_SSP,
49 MGMT_OP_SET_HS,
50 MGMT_OP_SET_LE,
51 MGMT_OP_SET_DEV_CLASS,
52 MGMT_OP_SET_LOCAL_NAME,
53 MGMT_OP_ADD_UUID,
54 MGMT_OP_REMOVE_UUID,
55 MGMT_OP_LOAD_LINK_KEYS,
56 MGMT_OP_LOAD_LONG_TERM_KEYS,
57 MGMT_OP_DISCONNECT,
58 MGMT_OP_GET_CONNECTIONS,
59 MGMT_OP_PIN_CODE_REPLY,
60 MGMT_OP_PIN_CODE_NEG_REPLY,
61 MGMT_OP_SET_IO_CAPABILITY,
62 MGMT_OP_PAIR_DEVICE,
63 MGMT_OP_CANCEL_PAIR_DEVICE,
64 MGMT_OP_UNPAIR_DEVICE,
65 MGMT_OP_USER_CONFIRM_REPLY,
66 MGMT_OP_USER_CONFIRM_NEG_REPLY,
67 MGMT_OP_USER_PASSKEY_REPLY,
68 MGMT_OP_USER_PASSKEY_NEG_REPLY,
69 MGMT_OP_READ_LOCAL_OOB_DATA,
70 MGMT_OP_ADD_REMOTE_OOB_DATA,
71 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
72 MGMT_OP_START_DISCOVERY,
73 MGMT_OP_STOP_DISCOVERY,
74 MGMT_OP_CONFIRM_NAME,
75 MGMT_OP_BLOCK_DEVICE,
76 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070077 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030078 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030079 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070080 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070081 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080082 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080083 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020084 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020085 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020086 MGMT_OP_GET_CONN_INFO,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020087};
88
89static const u16 mgmt_events[] = {
90 MGMT_EV_CONTROLLER_ERROR,
91 MGMT_EV_INDEX_ADDED,
92 MGMT_EV_INDEX_REMOVED,
93 MGMT_EV_NEW_SETTINGS,
94 MGMT_EV_CLASS_OF_DEV_CHANGED,
95 MGMT_EV_LOCAL_NAME_CHANGED,
96 MGMT_EV_NEW_LINK_KEY,
97 MGMT_EV_NEW_LONG_TERM_KEY,
98 MGMT_EV_DEVICE_CONNECTED,
99 MGMT_EV_DEVICE_DISCONNECTED,
100 MGMT_EV_CONNECT_FAILED,
101 MGMT_EV_PIN_CODE_REQUEST,
102 MGMT_EV_USER_CONFIRM_REQUEST,
103 MGMT_EV_USER_PASSKEY_REQUEST,
104 MGMT_EV_AUTH_FAILED,
105 MGMT_EV_DEVICE_FOUND,
106 MGMT_EV_DISCOVERING,
107 MGMT_EV_DEVICE_BLOCKED,
108 MGMT_EV_DEVICE_UNBLOCKED,
109 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300110 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800111 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700112 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200113};
114
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800115#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200116
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200117#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
118 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
119
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200120struct pending_cmd {
121 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200122 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200123 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100124 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200125 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300126 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200127};
128
Johan Hedbergca69b792011-11-11 18:10:00 +0200129/* HCI to MGMT error code conversion table */
130static u8 mgmt_status_table[] = {
131 MGMT_STATUS_SUCCESS,
132 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
133 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
134 MGMT_STATUS_FAILED, /* Hardware Failure */
135 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
136 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200137 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200138 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
139 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
140 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
141 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
142 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
143 MGMT_STATUS_BUSY, /* Command Disallowed */
144 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
145 MGMT_STATUS_REJECTED, /* Rejected Security */
146 MGMT_STATUS_REJECTED, /* Rejected Personal */
147 MGMT_STATUS_TIMEOUT, /* Host Timeout */
148 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
149 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
150 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
151 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
152 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
153 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
154 MGMT_STATUS_BUSY, /* Repeated Attempts */
155 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
156 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
157 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
158 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
159 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
160 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
161 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
162 MGMT_STATUS_FAILED, /* Unspecified Error */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
164 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
165 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
166 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
167 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
168 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
169 MGMT_STATUS_FAILED, /* Unit Link Key Used */
170 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
171 MGMT_STATUS_TIMEOUT, /* Instant Passed */
172 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
173 MGMT_STATUS_FAILED, /* Transaction Collision */
174 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
175 MGMT_STATUS_REJECTED, /* QoS Rejected */
176 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
177 MGMT_STATUS_REJECTED, /* Insufficient Security */
178 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
179 MGMT_STATUS_BUSY, /* Role Switch Pending */
180 MGMT_STATUS_FAILED, /* Slot Violation */
181 MGMT_STATUS_FAILED, /* Role Switch Failed */
182 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
183 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
184 MGMT_STATUS_BUSY, /* Host Busy Pairing */
185 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
186 MGMT_STATUS_BUSY, /* Controller Busy */
187 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
188 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
189 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
190 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
191 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
192};
193
194static u8 mgmt_status(u8 hci_status)
195{
196 if (hci_status < ARRAY_SIZE(mgmt_status_table))
197 return mgmt_status_table[hci_status];
198
199 return MGMT_STATUS_FAILED;
200}
201
Szymon Janc4e51eae2011-02-25 19:05:48 +0100202static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200203{
204 struct sk_buff *skb;
205 struct mgmt_hdr *hdr;
206 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300207 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200208
Szymon Janc34eb5252011-02-28 14:10:08 +0100209 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200210
Andre Guedes790eff42012-06-07 19:05:46 -0300211 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200212 if (!skb)
213 return -ENOMEM;
214
215 hdr = (void *) skb_put(skb, sizeof(*hdr));
216
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700217 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100218 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200219 hdr->len = cpu_to_le16(sizeof(*ev));
220
221 ev = (void *) skb_put(skb, sizeof(*ev));
222 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200223 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200224
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300225 err = sock_queue_rcv_skb(sk, skb);
226 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200227 kfree_skb(skb);
228
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300229 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200230}
231
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200232static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300233 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200234{
235 struct sk_buff *skb;
236 struct mgmt_hdr *hdr;
237 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300238 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200239
240 BT_DBG("sock %p", sk);
241
Andre Guedes790eff42012-06-07 19:05:46 -0300242 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200243 if (!skb)
244 return -ENOMEM;
245
246 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200247
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700248 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100249 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200250 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200251
Johan Hedberga38528f2011-01-22 06:46:43 +0200252 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200253 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200254 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100255
256 if (rp)
257 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200258
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300259 err = sock_queue_rcv_skb(sk, skb);
260 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200261 kfree_skb(skb);
262
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100263 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200264}
265
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300266static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
267 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200268{
269 struct mgmt_rp_read_version rp;
270
271 BT_DBG("sock %p", sk);
272
273 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700274 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200275
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200276 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300277 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200278}
279
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300280static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
281 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200282{
283 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200284 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
285 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200286 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200287 size_t rp_size;
288 int i, err;
289
290 BT_DBG("sock %p", sk);
291
292 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
293
294 rp = kmalloc(rp_size, GFP_KERNEL);
295 if (!rp)
296 return -ENOMEM;
297
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700298 rp->num_commands = cpu_to_le16(num_commands);
299 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200300
301 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
302 put_unaligned_le16(mgmt_commands[i], opcode);
303
304 for (i = 0; i < num_events; i++, opcode++)
305 put_unaligned_le16(mgmt_events[i], opcode);
306
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200307 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300308 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200309 kfree(rp);
310
311 return err;
312}
313
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300314static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
315 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200316{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200318 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200319 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200320 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300321 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200322
323 BT_DBG("sock %p", sk);
324
325 read_lock(&hci_dev_list_lock);
326
327 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300328 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700329 if (d->dev_type == HCI_BREDR)
330 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200331 }
332
Johan Hedberga38528f2011-01-22 06:46:43 +0200333 rp_len = sizeof(*rp) + (2 * count);
334 rp = kmalloc(rp_len, GFP_ATOMIC);
335 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100336 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200337 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100338 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200339
Johan Hedberg476e44c2012-10-19 20:10:46 +0300340 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200341 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200342 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200343 continue;
344
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700345 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
346 continue;
347
Marcel Holtmann1514b892013-10-06 08:25:01 -0700348 if (d->dev_type == HCI_BREDR) {
349 rp->index[count++] = cpu_to_le16(d->id);
350 BT_DBG("Added hci%u", d->id);
351 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200352 }
353
Johan Hedberg476e44c2012-10-19 20:10:46 +0300354 rp->num_controllers = cpu_to_le16(count);
355 rp_len = sizeof(*rp) + (2 * count);
356
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200357 read_unlock(&hci_dev_list_lock);
358
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200359 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300360 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361
Johan Hedberga38528f2011-01-22 06:46:43 +0200362 kfree(rp);
363
364 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365}
366
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200367static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200368{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200369 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200370
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200371 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800373 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200374
Andre Guedesed3fa312012-07-24 15:03:46 -0300375 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300376 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500377 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
378 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300379 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200380 settings |= MGMT_SETTING_BREDR;
381 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700382
383 if (lmp_ssp_capable(hdev)) {
384 settings |= MGMT_SETTING_SSP;
385 settings |= MGMT_SETTING_HS;
386 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800387
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800388 if (lmp_sc_capable(hdev) ||
389 test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800390 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700391 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100392
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300393 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200394 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300395 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200396 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300397 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200398
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200399 return settings;
400}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200401
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200402static u32 get_current_settings(struct hci_dev *hdev)
403{
404 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200405
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200406 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100407 settings |= MGMT_SETTING_POWERED;
408
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200409 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200410 settings |= MGMT_SETTING_CONNECTABLE;
411
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500412 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
413 settings |= MGMT_SETTING_FAST_CONNECTABLE;
414
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200415 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200416 settings |= MGMT_SETTING_DISCOVERABLE;
417
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200418 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200419 settings |= MGMT_SETTING_PAIRABLE;
420
Johan Hedberg56f87902013-10-02 13:43:13 +0300421 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200422 settings |= MGMT_SETTING_BREDR;
423
Johan Hedberg06199cf2012-02-22 16:37:11 +0200424 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200425 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200426
Johan Hedberg47990ea2012-02-22 11:58:37 +0200427 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200428 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200429
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200430 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200431 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200432
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200433 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
434 settings |= MGMT_SETTING_HS;
435
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200436 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300437 settings |= MGMT_SETTING_ADVERTISING;
438
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800439 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
440 settings |= MGMT_SETTING_SECURE_CONN;
441
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800442 if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags))
443 settings |= MGMT_SETTING_DEBUG_KEYS;
444
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200445 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
446 settings |= MGMT_SETTING_PRIVACY;
447
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200448 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200449}
450
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300451#define PNP_INFO_SVCLASS_ID 0x1200
452
Johan Hedberg213202e2013-01-27 00:31:33 +0200453static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
454{
455 u8 *ptr = data, *uuids_start = NULL;
456 struct bt_uuid *uuid;
457
458 if (len < 4)
459 return ptr;
460
461 list_for_each_entry(uuid, &hdev->uuids, list) {
462 u16 uuid16;
463
464 if (uuid->size != 16)
465 continue;
466
467 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
468 if (uuid16 < 0x1100)
469 continue;
470
471 if (uuid16 == PNP_INFO_SVCLASS_ID)
472 continue;
473
474 if (!uuids_start) {
475 uuids_start = ptr;
476 uuids_start[0] = 1;
477 uuids_start[1] = EIR_UUID16_ALL;
478 ptr += 2;
479 }
480
481 /* Stop if not enough space to put next UUID */
482 if ((ptr - data) + sizeof(u16) > len) {
483 uuids_start[1] = EIR_UUID16_SOME;
484 break;
485 }
486
487 *ptr++ = (uuid16 & 0x00ff);
488 *ptr++ = (uuid16 & 0xff00) >> 8;
489 uuids_start[0] += sizeof(uuid16);
490 }
491
492 return ptr;
493}
494
Johan Hedbergcdf19632013-01-27 00:31:34 +0200495static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
496{
497 u8 *ptr = data, *uuids_start = NULL;
498 struct bt_uuid *uuid;
499
500 if (len < 6)
501 return ptr;
502
503 list_for_each_entry(uuid, &hdev->uuids, list) {
504 if (uuid->size != 32)
505 continue;
506
507 if (!uuids_start) {
508 uuids_start = ptr;
509 uuids_start[0] = 1;
510 uuids_start[1] = EIR_UUID32_ALL;
511 ptr += 2;
512 }
513
514 /* Stop if not enough space to put next UUID */
515 if ((ptr - data) + sizeof(u32) > len) {
516 uuids_start[1] = EIR_UUID32_SOME;
517 break;
518 }
519
520 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
521 ptr += sizeof(u32);
522 uuids_start[0] += sizeof(u32);
523 }
524
525 return ptr;
526}
527
Johan Hedbergc00d5752013-01-27 00:31:35 +0200528static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
529{
530 u8 *ptr = data, *uuids_start = NULL;
531 struct bt_uuid *uuid;
532
533 if (len < 18)
534 return ptr;
535
536 list_for_each_entry(uuid, &hdev->uuids, list) {
537 if (uuid->size != 128)
538 continue;
539
540 if (!uuids_start) {
541 uuids_start = ptr;
542 uuids_start[0] = 1;
543 uuids_start[1] = EIR_UUID128_ALL;
544 ptr += 2;
545 }
546
547 /* Stop if not enough space to put next UUID */
548 if ((ptr - data) + 16 > len) {
549 uuids_start[1] = EIR_UUID128_SOME;
550 break;
551 }
552
553 memcpy(ptr, uuid->uuid, 16);
554 ptr += 16;
555 uuids_start[0] += 16;
556 }
557
558 return ptr;
559}
560
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300561static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
562{
563 struct pending_cmd *cmd;
564
565 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
566 if (cmd->opcode == opcode)
567 return cmd;
568 }
569
570 return NULL;
571}
572
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700573static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
574{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700575 u8 ad_len = 0;
576 size_t name_len;
577
578 name_len = strlen(hdev->dev_name);
579 if (name_len > 0) {
580 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
581
582 if (name_len > max_len) {
583 name_len = max_len;
584 ptr[1] = EIR_NAME_SHORT;
585 } else
586 ptr[1] = EIR_NAME_COMPLETE;
587
588 ptr[0] = name_len + 1;
589
590 memcpy(ptr + 2, hdev->dev_name, name_len);
591
592 ad_len += (name_len + 2);
593 ptr += (name_len + 2);
594 }
595
596 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700597}
598
599static void update_scan_rsp_data(struct hci_request *req)
600{
601 struct hci_dev *hdev = req->hdev;
602 struct hci_cp_le_set_scan_rsp_data cp;
603 u8 len;
604
Johan Hedberg7751ef12013-10-19 23:38:15 +0300605 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700606 return;
607
608 memset(&cp, 0, sizeof(cp));
609
610 len = create_scan_rsp_data(hdev, cp.data);
611
Johan Hedbergeb438b52013-10-16 15:31:07 +0300612 if (hdev->scan_rsp_data_len == len &&
613 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700614 return;
615
Johan Hedbergeb438b52013-10-16 15:31:07 +0300616 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
617 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700618
619 cp.length = len;
620
621 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
622}
623
Johan Hedberg9a43e252013-10-20 19:00:07 +0300624static u8 get_adv_discov_flags(struct hci_dev *hdev)
625{
626 struct pending_cmd *cmd;
627
628 /* If there's a pending mgmt command the flags will not yet have
629 * their final values, so check for this first.
630 */
631 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
632 if (cmd) {
633 struct mgmt_mode *cp = cmd->param;
634 if (cp->val == 0x01)
635 return LE_AD_GENERAL;
636 else if (cp->val == 0x02)
637 return LE_AD_LIMITED;
638 } else {
639 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
640 return LE_AD_LIMITED;
641 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
642 return LE_AD_GENERAL;
643 }
644
645 return 0;
646}
647
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700648static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700649{
650 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700651
Johan Hedberg9a43e252013-10-20 19:00:07 +0300652 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700653
Johan Hedberge8340042014-01-30 11:16:50 -0800654 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700655 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700656
657 if (flags) {
658 BT_DBG("adv flags 0x%02x", flags);
659
660 ptr[0] = 2;
661 ptr[1] = EIR_FLAGS;
662 ptr[2] = flags;
663
664 ad_len += 3;
665 ptr += 3;
666 }
667
668 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
669 ptr[0] = 2;
670 ptr[1] = EIR_TX_POWER;
671 ptr[2] = (u8) hdev->adv_tx_power;
672
673 ad_len += 3;
674 ptr += 3;
675 }
676
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700677 return ad_len;
678}
679
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700680static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700681{
682 struct hci_dev *hdev = req->hdev;
683 struct hci_cp_le_set_adv_data cp;
684 u8 len;
685
Johan Hedberg10994ce2013-10-19 23:38:16 +0300686 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700687 return;
688
689 memset(&cp, 0, sizeof(cp));
690
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700691 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700692
693 if (hdev->adv_data_len == len &&
694 memcmp(cp.data, hdev->adv_data, len) == 0)
695 return;
696
697 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
698 hdev->adv_data_len = len;
699
700 cp.length = len;
701
702 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
703}
704
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300705static void create_eir(struct hci_dev *hdev, u8 *data)
706{
707 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300708 size_t name_len;
709
710 name_len = strlen(hdev->dev_name);
711
712 if (name_len > 0) {
713 /* EIR Data type */
714 if (name_len > 48) {
715 name_len = 48;
716 ptr[1] = EIR_NAME_SHORT;
717 } else
718 ptr[1] = EIR_NAME_COMPLETE;
719
720 /* EIR Data length */
721 ptr[0] = name_len + 1;
722
723 memcpy(ptr + 2, hdev->dev_name, name_len);
724
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300725 ptr += (name_len + 2);
726 }
727
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100728 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700729 ptr[0] = 2;
730 ptr[1] = EIR_TX_POWER;
731 ptr[2] = (u8) hdev->inq_tx_power;
732
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700733 ptr += 3;
734 }
735
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700736 if (hdev->devid_source > 0) {
737 ptr[0] = 9;
738 ptr[1] = EIR_DEVICE_ID;
739
740 put_unaligned_le16(hdev->devid_source, ptr + 2);
741 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
742 put_unaligned_le16(hdev->devid_product, ptr + 6);
743 put_unaligned_le16(hdev->devid_version, ptr + 8);
744
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700745 ptr += 10;
746 }
747
Johan Hedberg213202e2013-01-27 00:31:33 +0200748 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200749 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200750 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300751}
752
Johan Hedberg890ea892013-03-15 17:06:52 -0500753static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300754{
Johan Hedberg890ea892013-03-15 17:06:52 -0500755 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300756 struct hci_cp_write_eir cp;
757
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200758 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500759 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200760
Johan Hedberg976eb202012-10-24 21:12:01 +0300761 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500762 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300763
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200764 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500765 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300766
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200767 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500768 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300769
770 memset(&cp, 0, sizeof(cp));
771
772 create_eir(hdev, cp.data);
773
774 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500775 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300776
777 memcpy(hdev->eir, cp.data, sizeof(cp.data));
778
Johan Hedberg890ea892013-03-15 17:06:52 -0500779 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300780}
781
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200782static u8 get_service_classes(struct hci_dev *hdev)
783{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300784 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200785 u8 val = 0;
786
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300787 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200788 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200789
790 return val;
791}
792
Johan Hedberg890ea892013-03-15 17:06:52 -0500793static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200794{
Johan Hedberg890ea892013-03-15 17:06:52 -0500795 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200796 u8 cod[3];
797
798 BT_DBG("%s", hdev->name);
799
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200800 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500801 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200802
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300803 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
804 return;
805
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200806 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500807 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200808
809 cod[0] = hdev->minor_class;
810 cod[1] = hdev->major_class;
811 cod[2] = get_service_classes(hdev);
812
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700813 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
814 cod[1] |= 0x20;
815
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200816 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500817 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200818
Johan Hedberg890ea892013-03-15 17:06:52 -0500819 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200820}
821
Johan Hedberga4858cb2014-02-25 19:56:31 +0200822static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200823{
824 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200825
826 /* If there's a pending mgmt command the flag will not yet have
827 * it's final value, so check for this first.
828 */
829 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
830 if (cmd) {
831 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200832 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200833 }
834
Johan Hedberga4858cb2014-02-25 19:56:31 +0200835 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200836}
837
838static void enable_advertising(struct hci_request *req)
839{
840 struct hci_dev *hdev = req->hdev;
841 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200842 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200843 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200844
Johan Hedberg8d972502014-02-28 12:54:14 +0200845 /* Clear the HCI_ADVERTISING bit temporarily so that the
846 * hci_update_random_address knows that it's safe to go ahead
847 * and write a new random address. The flag will be set back on
848 * as soon as the SET_ADV_ENABLE HCI command completes.
849 */
850 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
851
Johan Hedberga4858cb2014-02-25 19:56:31 +0200852 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200853
Johan Hedberga4858cb2014-02-25 19:56:31 +0200854 /* Set require_privacy to true only when non-connectable
855 * advertising is used. In that case it is fine to use a
856 * non-resolvable private address.
857 */
858 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200859 return;
860
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800861 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700862 cp.min_interval = cpu_to_le16(0x0800);
863 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200864 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200865 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200866 cp.channel_map = hdev->le_adv_channel_map;
867
868 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
869
870 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
871}
872
873static void disable_advertising(struct hci_request *req)
874{
875 u8 enable = 0x00;
876
877 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
878}
879
Johan Hedberg7d785252011-12-15 00:47:39 +0200880static void service_cache_off(struct work_struct *work)
881{
882 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300883 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500884 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200885
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200886 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200887 return;
888
Johan Hedberg890ea892013-03-15 17:06:52 -0500889 hci_req_init(&req, hdev);
890
Johan Hedberg7d785252011-12-15 00:47:39 +0200891 hci_dev_lock(hdev);
892
Johan Hedberg890ea892013-03-15 17:06:52 -0500893 update_eir(&req);
894 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200895
896 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500897
898 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200899}
900
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200901static void rpa_expired(struct work_struct *work)
902{
903 struct hci_dev *hdev = container_of(work, struct hci_dev,
904 rpa_expired.work);
905 struct hci_request req;
906
907 BT_DBG("");
908
909 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
910
911 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
912 hci_conn_num(hdev, LE_LINK) > 0)
913 return;
914
915 /* The generation of a new RPA and programming it into the
916 * controller happens in the enable_advertising() function.
917 */
918
919 hci_req_init(&req, hdev);
920
921 disable_advertising(&req);
922 enable_advertising(&req);
923
924 hci_req_run(&req, NULL);
925}
926
Johan Hedberg6a919082012-02-28 06:17:26 +0200927static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200928{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200929 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200930 return;
931
Johan Hedberg4f87da82012-03-02 19:55:56 +0200932 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200933 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200934
Johan Hedberg4f87da82012-03-02 19:55:56 +0200935 /* Non-mgmt controlled devices get this bit set
936 * implicitly so that pairing works for them, however
937 * for mgmt we require user-space to explicitly enable
938 * it
939 */
940 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200941}
942
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200943static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300944 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200945{
946 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200947
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200948 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200949
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300950 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200951
Johan Hedberg03811012010-12-08 00:21:06 +0200952 memset(&rp, 0, sizeof(rp));
953
Johan Hedberg03811012010-12-08 00:21:06 +0200954 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200955
956 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200957 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200958
959 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
960 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
961
962 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200963
964 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200965 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200966
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300967 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200968
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200969 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300970 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200971}
972
973static void mgmt_pending_free(struct pending_cmd *cmd)
974{
975 sock_put(cmd->sk);
976 kfree(cmd->param);
977 kfree(cmd);
978}
979
980static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300981 struct hci_dev *hdev, void *data,
982 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200983{
984 struct pending_cmd *cmd;
985
Andre Guedes12b94562012-06-07 19:05:45 -0300986 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200987 if (!cmd)
988 return NULL;
989
990 cmd->opcode = opcode;
991 cmd->index = hdev->id;
992
Andre Guedes12b94562012-06-07 19:05:45 -0300993 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200994 if (!cmd->param) {
995 kfree(cmd);
996 return NULL;
997 }
998
999 if (data)
1000 memcpy(cmd->param, data, len);
1001
1002 cmd->sk = sk;
1003 sock_hold(sk);
1004
1005 list_add(&cmd->list, &hdev->mgmt_pending);
1006
1007 return cmd;
1008}
1009
1010static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001011 void (*cb)(struct pending_cmd *cmd,
1012 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001013 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001014{
Andre Guedesa3d09352013-02-01 11:21:30 -03001015 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001016
Andre Guedesa3d09352013-02-01 11:21:30 -03001017 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001018 if (opcode > 0 && cmd->opcode != opcode)
1019 continue;
1020
1021 cb(cmd, data);
1022 }
1023}
1024
Johan Hedberg03811012010-12-08 00:21:06 +02001025static void mgmt_pending_remove(struct pending_cmd *cmd)
1026{
1027 list_del(&cmd->list);
1028 mgmt_pending_free(cmd);
1029}
1030
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001031static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001032{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001033 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001034
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001035 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001036 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001037}
1038
Johan Hedberg8b064a32014-02-24 14:52:22 +02001039static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1040{
1041 BT_DBG("%s status 0x%02x", hdev->name, status);
1042
Johan Hedberga3172b72014-02-28 09:33:44 +02001043 if (hci_conn_count(hdev) == 0) {
1044 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001045 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001046 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001047}
1048
1049static int clean_up_hci_state(struct hci_dev *hdev)
1050{
1051 struct hci_request req;
1052 struct hci_conn *conn;
1053
1054 hci_req_init(&req, hdev);
1055
1056 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1057 test_bit(HCI_PSCAN, &hdev->flags)) {
1058 u8 scan = 0x00;
1059 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1060 }
1061
1062 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1063 disable_advertising(&req);
1064
1065 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Andre Guedesb1efcc22014-02-26 20:21:40 -03001066 hci_req_add_le_scan_disable(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001067 }
1068
1069 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1070 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001071 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001072
Johan Hedbergc9910d02014-02-27 14:35:12 +02001073 switch (conn->state) {
1074 case BT_CONNECTED:
1075 case BT_CONFIG:
1076 dc.handle = cpu_to_le16(conn->handle);
1077 dc.reason = 0x15; /* Terminated due to Power Off */
1078 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1079 break;
1080 case BT_CONNECT:
1081 if (conn->type == LE_LINK)
1082 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1083 0, NULL);
1084 else if (conn->type == ACL_LINK)
1085 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1086 6, &conn->dst);
1087 break;
1088 case BT_CONNECT2:
1089 bacpy(&rej.bdaddr, &conn->dst);
1090 rej.reason = 0x15; /* Terminated due to Power Off */
1091 if (conn->type == ACL_LINK)
1092 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1093 sizeof(rej), &rej);
1094 else if (conn->type == SCO_LINK)
1095 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1096 sizeof(rej), &rej);
1097 break;
1098 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001099 }
1100
1101 return hci_req_run(&req, clean_up_hci_complete);
1102}
1103
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001104static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001105 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001106{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001107 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001108 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001109 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001110
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001111 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001112
Johan Hedberga7e80f22013-01-09 16:05:19 +02001113 if (cp->val != 0x00 && cp->val != 0x01)
1114 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1115 MGMT_STATUS_INVALID_PARAMS);
1116
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001117 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001118
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001119 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1120 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1121 MGMT_STATUS_BUSY);
1122 goto failed;
1123 }
1124
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001125 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1126 cancel_delayed_work(&hdev->power_off);
1127
1128 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001129 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1130 data, len);
1131 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001132 goto failed;
1133 }
1134 }
1135
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001136 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001137 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001138 goto failed;
1139 }
1140
Johan Hedberg03811012010-12-08 00:21:06 +02001141 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1142 if (!cmd) {
1143 err = -ENOMEM;
1144 goto failed;
1145 }
1146
Johan Hedberg8b064a32014-02-24 14:52:22 +02001147 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001148 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001149 err = 0;
1150 } else {
1151 /* Disconnect connections, stop scans, etc */
1152 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001153 if (!err)
1154 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1155 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001156
Johan Hedberg8b064a32014-02-24 14:52:22 +02001157 /* ENODATA means there were no HCI commands queued */
1158 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001159 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001160 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1161 err = 0;
1162 }
1163 }
Johan Hedberg03811012010-12-08 00:21:06 +02001164
1165failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167 return err;
1168}
1169
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001170static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1171 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001172{
1173 struct sk_buff *skb;
1174 struct mgmt_hdr *hdr;
1175
Andre Guedes790eff42012-06-07 19:05:46 -03001176 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001177 if (!skb)
1178 return -ENOMEM;
1179
1180 hdr = (void *) skb_put(skb, sizeof(*hdr));
1181 hdr->opcode = cpu_to_le16(event);
1182 if (hdev)
1183 hdr->index = cpu_to_le16(hdev->id);
1184 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001185 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001186 hdr->len = cpu_to_le16(data_len);
1187
1188 if (data)
1189 memcpy(skb_put(skb, data_len), data, data_len);
1190
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001191 /* Time stamp */
1192 __net_timestamp(skb);
1193
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001194 hci_send_to_control(skb, skip_sk);
1195 kfree_skb(skb);
1196
1197 return 0;
1198}
1199
1200static int new_settings(struct hci_dev *hdev, struct sock *skip)
1201{
1202 __le32 ev;
1203
1204 ev = cpu_to_le32(get_current_settings(hdev));
1205
1206 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1207}
1208
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001209struct cmd_lookup {
1210 struct sock *sk;
1211 struct hci_dev *hdev;
1212 u8 mgmt_status;
1213};
1214
1215static void settings_rsp(struct pending_cmd *cmd, void *data)
1216{
1217 struct cmd_lookup *match = data;
1218
1219 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1220
1221 list_del(&cmd->list);
1222
1223 if (match->sk == NULL) {
1224 match->sk = cmd->sk;
1225 sock_hold(match->sk);
1226 }
1227
1228 mgmt_pending_free(cmd);
1229}
1230
1231static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1232{
1233 u8 *status = data;
1234
1235 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1236 mgmt_pending_remove(cmd);
1237}
1238
Johan Hedberge6fe7982013-10-02 15:45:22 +03001239static u8 mgmt_bredr_support(struct hci_dev *hdev)
1240{
1241 if (!lmp_bredr_capable(hdev))
1242 return MGMT_STATUS_NOT_SUPPORTED;
1243 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1244 return MGMT_STATUS_REJECTED;
1245 else
1246 return MGMT_STATUS_SUCCESS;
1247}
1248
1249static u8 mgmt_le_support(struct hci_dev *hdev)
1250{
1251 if (!lmp_le_capable(hdev))
1252 return MGMT_STATUS_NOT_SUPPORTED;
1253 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1254 return MGMT_STATUS_REJECTED;
1255 else
1256 return MGMT_STATUS_SUCCESS;
1257}
1258
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001259static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1260{
1261 struct pending_cmd *cmd;
1262 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001263 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001264 bool changed;
1265
1266 BT_DBG("status 0x%02x", status);
1267
1268 hci_dev_lock(hdev);
1269
1270 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1271 if (!cmd)
1272 goto unlock;
1273
1274 if (status) {
1275 u8 mgmt_err = mgmt_status(status);
1276 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001277 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001278 goto remove_cmd;
1279 }
1280
1281 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001282 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001283 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1284 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001285
1286 if (hdev->discov_timeout > 0) {
1287 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1288 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1289 to);
1290 }
1291 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001292 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1293 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001294 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001295
1296 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1297
1298 if (changed)
1299 new_settings(hdev, cmd->sk);
1300
Marcel Holtmann970ba522013-10-15 06:33:57 -07001301 /* When the discoverable mode gets changed, make sure
1302 * that class of device has the limited discoverable
1303 * bit correctly set.
1304 */
1305 hci_req_init(&req, hdev);
1306 update_class(&req);
1307 hci_req_run(&req, NULL);
1308
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001309remove_cmd:
1310 mgmt_pending_remove(cmd);
1311
1312unlock:
1313 hci_dev_unlock(hdev);
1314}
1315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001316static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001317 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001318{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001319 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001320 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001321 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001322 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001323 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001324 int err;
1325
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001326 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001327
Johan Hedberg9a43e252013-10-20 19:00:07 +03001328 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1329 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001330 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001331 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001332
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001333 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001334 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1335 MGMT_STATUS_INVALID_PARAMS);
1336
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001337 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001338
1339 /* Disabling discoverable requires that no timeout is set,
1340 * and enabling limited discoverable requires a timeout.
1341 */
1342 if ((cp->val == 0x00 && timeout > 0) ||
1343 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001344 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001345 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001346
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001347 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001348
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001349 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001350 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001351 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001352 goto failed;
1353 }
1354
1355 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001356 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001357 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001358 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001359 goto failed;
1360 }
1361
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001362 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001363 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001364 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001365 goto failed;
1366 }
1367
1368 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001369 bool changed = false;
1370
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001371 /* Setting limited discoverable when powered off is
1372 * not a valid operation since it requires a timeout
1373 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1374 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001375 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1376 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1377 changed = true;
1378 }
1379
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001380 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001381 if (err < 0)
1382 goto failed;
1383
1384 if (changed)
1385 err = new_settings(hdev, sk);
1386
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001387 goto failed;
1388 }
1389
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001390 /* If the current mode is the same, then just update the timeout
1391 * value with the new value. And if only the timeout gets updated,
1392 * then no need for any HCI transactions.
1393 */
1394 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1395 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1396 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001397 cancel_delayed_work(&hdev->discov_off);
1398 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001399
Marcel Holtmann36261542013-10-15 08:28:51 -07001400 if (cp->val && hdev->discov_timeout > 0) {
1401 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001402 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001403 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001404 }
1405
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001406 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001407 goto failed;
1408 }
1409
1410 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1411 if (!cmd) {
1412 err = -ENOMEM;
1413 goto failed;
1414 }
1415
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001416 /* Cancel any potential discoverable timeout that might be
1417 * still active and store new timeout value. The arming of
1418 * the timeout happens in the complete handler.
1419 */
1420 cancel_delayed_work(&hdev->discov_off);
1421 hdev->discov_timeout = timeout;
1422
Johan Hedbergb456f872013-10-19 23:38:22 +03001423 /* Limited discoverable mode */
1424 if (cp->val == 0x02)
1425 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1426 else
1427 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1428
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001429 hci_req_init(&req, hdev);
1430
Johan Hedberg9a43e252013-10-20 19:00:07 +03001431 /* The procedure for LE-only controllers is much simpler - just
1432 * update the advertising data.
1433 */
1434 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1435 goto update_ad;
1436
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001437 scan = SCAN_PAGE;
1438
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001439 if (cp->val) {
1440 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001441
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001442 if (cp->val == 0x02) {
1443 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001444 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001445 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1446 hci_cp.iac_lap[1] = 0x8b;
1447 hci_cp.iac_lap[2] = 0x9e;
1448 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1449 hci_cp.iac_lap[4] = 0x8b;
1450 hci_cp.iac_lap[5] = 0x9e;
1451 } else {
1452 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001453 hci_cp.num_iac = 1;
1454 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1455 hci_cp.iac_lap[1] = 0x8b;
1456 hci_cp.iac_lap[2] = 0x9e;
1457 }
1458
1459 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1460 (hci_cp.num_iac * 3) + 1, &hci_cp);
1461
1462 scan |= SCAN_INQUIRY;
1463 } else {
1464 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1465 }
1466
1467 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001468
Johan Hedberg9a43e252013-10-20 19:00:07 +03001469update_ad:
1470 update_adv_data(&req);
1471
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001472 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001473 if (err < 0)
1474 mgmt_pending_remove(cmd);
1475
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001476failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001477 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001478 return err;
1479}
1480
Johan Hedberg406d7802013-03-15 17:07:09 -05001481static void write_fast_connectable(struct hci_request *req, bool enable)
1482{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001483 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001484 struct hci_cp_write_page_scan_activity acp;
1485 u8 type;
1486
Johan Hedberg547003b2013-10-21 16:51:53 +03001487 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1488 return;
1489
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001490 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1491 return;
1492
Johan Hedberg406d7802013-03-15 17:07:09 -05001493 if (enable) {
1494 type = PAGE_SCAN_TYPE_INTERLACED;
1495
1496 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001497 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001498 } else {
1499 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1500
1501 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001502 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001503 }
1504
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001505 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001506
Johan Hedbergbd98b992013-03-15 17:07:13 -05001507 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1508 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1509 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1510 sizeof(acp), &acp);
1511
1512 if (hdev->page_scan_type != type)
1513 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001514}
1515
Johan Hedberg2b76f452013-03-15 17:07:04 -05001516static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1517{
1518 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001519 struct mgmt_mode *cp;
1520 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001521
1522 BT_DBG("status 0x%02x", status);
1523
1524 hci_dev_lock(hdev);
1525
1526 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1527 if (!cmd)
1528 goto unlock;
1529
Johan Hedberg37438c12013-10-14 16:20:05 +03001530 if (status) {
1531 u8 mgmt_err = mgmt_status(status);
1532 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1533 goto remove_cmd;
1534 }
1535
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001536 cp = cmd->param;
1537 if (cp->val)
1538 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1539 else
1540 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1541
Johan Hedberg2b76f452013-03-15 17:07:04 -05001542 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1543
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001544 if (changed)
1545 new_settings(hdev, cmd->sk);
1546
Johan Hedberg37438c12013-10-14 16:20:05 +03001547remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001548 mgmt_pending_remove(cmd);
1549
1550unlock:
1551 hci_dev_unlock(hdev);
1552}
1553
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001554static int set_connectable_update_settings(struct hci_dev *hdev,
1555 struct sock *sk, u8 val)
1556{
1557 bool changed = false;
1558 int err;
1559
1560 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1561 changed = true;
1562
1563 if (val) {
1564 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1565 } else {
1566 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1567 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1568 }
1569
1570 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1571 if (err < 0)
1572 return err;
1573
1574 if (changed)
1575 return new_settings(hdev, sk);
1576
1577 return 0;
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001584 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001585 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001586 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001587 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001589 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001590
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001591 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1592 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001593 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001594 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001595
Johan Hedberga7e80f22013-01-09 16:05:19 +02001596 if (cp->val != 0x00 && cp->val != 0x01)
1597 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1598 MGMT_STATUS_INVALID_PARAMS);
1599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001600 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001601
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001602 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001603 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001604 goto failed;
1605 }
1606
1607 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001608 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001609 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001610 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001611 goto failed;
1612 }
1613
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001614 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1615 if (!cmd) {
1616 err = -ENOMEM;
1617 goto failed;
1618 }
1619
Johan Hedberg2b76f452013-03-15 17:07:04 -05001620 hci_req_init(&req, hdev);
1621
Johan Hedberg9a43e252013-10-20 19:00:07 +03001622 /* If BR/EDR is not enabled and we disable advertising as a
1623 * by-product of disabling connectable, we need to update the
1624 * advertising flags.
1625 */
1626 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1627 if (!cp->val) {
1628 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1629 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1630 }
1631 update_adv_data(&req);
1632 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001633 if (cp->val) {
1634 scan = SCAN_PAGE;
1635 } else {
1636 scan = 0;
1637
1638 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001639 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001640 cancel_delayed_work(&hdev->discov_off);
1641 }
1642
1643 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1644 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001645
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001646 /* If we're going from non-connectable to connectable or
1647 * vice-versa when fast connectable is enabled ensure that fast
1648 * connectable gets disabled. write_fast_connectable won't do
1649 * anything if the page scan parameters are already what they
1650 * should be.
1651 */
1652 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001653 write_fast_connectable(&req, false);
1654
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001655 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1656 hci_conn_num(hdev, LE_LINK) == 0) {
1657 disable_advertising(&req);
1658 enable_advertising(&req);
1659 }
1660
Johan Hedberg2b76f452013-03-15 17:07:04 -05001661 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001662 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001663 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001664 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001665 err = set_connectable_update_settings(hdev, sk,
1666 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001667 goto failed;
1668 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001669
1670failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001671 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001672 return err;
1673}
1674
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001675static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001676 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001677{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001678 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001679 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001680 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001681
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001682 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001683
Johan Hedberga7e80f22013-01-09 16:05:19 +02001684 if (cp->val != 0x00 && cp->val != 0x01)
1685 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1686 MGMT_STATUS_INVALID_PARAMS);
1687
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001688 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001689
1690 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001691 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001692 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001693 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001694
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001695 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001696 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001697 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001698
Marcel Holtmann55594352013-10-06 16:11:57 -07001699 if (changed)
1700 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001701
Marcel Holtmann55594352013-10-06 16:11:57 -07001702unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001703 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001704 return err;
1705}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001706
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001707static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1708 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001709{
1710 struct mgmt_mode *cp = data;
1711 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001712 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001713 int err;
1714
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001715 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001716
Johan Hedberge6fe7982013-10-02 15:45:22 +03001717 status = mgmt_bredr_support(hdev);
1718 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001719 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001720 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001721
Johan Hedberga7e80f22013-01-09 16:05:19 +02001722 if (cp->val != 0x00 && cp->val != 0x01)
1723 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1724 MGMT_STATUS_INVALID_PARAMS);
1725
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001726 hci_dev_lock(hdev);
1727
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001728 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001729 bool changed = false;
1730
1731 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001732 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001733 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1734 changed = true;
1735 }
1736
1737 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1738 if (err < 0)
1739 goto failed;
1740
1741 if (changed)
1742 err = new_settings(hdev, sk);
1743
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001744 goto failed;
1745 }
1746
1747 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001748 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001749 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001750 goto failed;
1751 }
1752
1753 val = !!cp->val;
1754
1755 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1756 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1757 goto failed;
1758 }
1759
1760 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1761 if (!cmd) {
1762 err = -ENOMEM;
1763 goto failed;
1764 }
1765
1766 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1767 if (err < 0) {
1768 mgmt_pending_remove(cmd);
1769 goto failed;
1770 }
1771
1772failed:
1773 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001774 return err;
1775}
1776
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001777static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001778{
1779 struct mgmt_mode *cp = data;
1780 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001781 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001782 int err;
1783
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001784 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001785
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001786 status = mgmt_bredr_support(hdev);
1787 if (status)
1788 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1789
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001790 if (!lmp_ssp_capable(hdev))
1791 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1792 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001793
Johan Hedberga7e80f22013-01-09 16:05:19 +02001794 if (cp->val != 0x00 && cp->val != 0x01)
1795 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1796 MGMT_STATUS_INVALID_PARAMS);
1797
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001798 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001799
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001800 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001801 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001802
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001803 if (cp->val) {
1804 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1805 &hdev->dev_flags);
1806 } else {
1807 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1808 &hdev->dev_flags);
1809 if (!changed)
1810 changed = test_and_clear_bit(HCI_HS_ENABLED,
1811 &hdev->dev_flags);
1812 else
1813 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001814 }
1815
1816 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1817 if (err < 0)
1818 goto failed;
1819
1820 if (changed)
1821 err = new_settings(hdev, sk);
1822
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001823 goto failed;
1824 }
1825
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001826 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1827 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001828 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1829 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001830 goto failed;
1831 }
1832
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001833 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001834 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1835 goto failed;
1836 }
1837
1838 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1839 if (!cmd) {
1840 err = -ENOMEM;
1841 goto failed;
1842 }
1843
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001844 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001845 if (err < 0) {
1846 mgmt_pending_remove(cmd);
1847 goto failed;
1848 }
1849
1850failed:
1851 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001852 return err;
1853}
1854
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001855static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001856{
1857 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001858 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001859 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001860 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001861
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001862 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001863
Johan Hedberge6fe7982013-10-02 15:45:22 +03001864 status = mgmt_bredr_support(hdev);
1865 if (status)
1866 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001867
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001868 if (!lmp_ssp_capable(hdev))
1869 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1870 MGMT_STATUS_NOT_SUPPORTED);
1871
1872 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1873 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1874 MGMT_STATUS_REJECTED);
1875
Johan Hedberga7e80f22013-01-09 16:05:19 +02001876 if (cp->val != 0x00 && cp->val != 0x01)
1877 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1878 MGMT_STATUS_INVALID_PARAMS);
1879
Marcel Holtmannee392692013-10-01 22:59:23 -07001880 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001881
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001882 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001883 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001884 } else {
1885 if (hdev_is_powered(hdev)) {
1886 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1887 MGMT_STATUS_REJECTED);
1888 goto unlock;
1889 }
1890
Marcel Holtmannee392692013-10-01 22:59:23 -07001891 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001892 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001893
1894 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1895 if (err < 0)
1896 goto unlock;
1897
1898 if (changed)
1899 err = new_settings(hdev, sk);
1900
1901unlock:
1902 hci_dev_unlock(hdev);
1903 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001904}
1905
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001906static void le_enable_complete(struct hci_dev *hdev, u8 status)
1907{
1908 struct cmd_lookup match = { NULL, hdev };
1909
1910 if (status) {
1911 u8 mgmt_err = mgmt_status(status);
1912
1913 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1914 &mgmt_err);
1915 return;
1916 }
1917
1918 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1919
1920 new_settings(hdev, match.sk);
1921
1922 if (match.sk)
1923 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001924
1925 /* Make sure the controller has a good default for
1926 * advertising data. Restrict the update to when LE
1927 * has actually been enabled. During power on, the
1928 * update in powered_update_hci will take care of it.
1929 */
1930 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1931 struct hci_request req;
1932
1933 hci_dev_lock(hdev);
1934
1935 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001936 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001937 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001938 hci_req_run(&req, NULL);
1939
1940 hci_dev_unlock(hdev);
1941 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001942}
1943
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001944static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001945{
1946 struct mgmt_mode *cp = data;
1947 struct hci_cp_write_le_host_supported hci_cp;
1948 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001949 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001950 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001951 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001952
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001953 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001954
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001955 if (!lmp_le_capable(hdev))
1956 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1957 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001958
Johan Hedberga7e80f22013-01-09 16:05:19 +02001959 if (cp->val != 0x00 && cp->val != 0x01)
1960 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1961 MGMT_STATUS_INVALID_PARAMS);
1962
Johan Hedbergc73eee92013-04-19 18:35:21 +03001963 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03001964 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03001965 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1966 MGMT_STATUS_REJECTED);
1967
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001968 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001969
1970 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02001971 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001972
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001973 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02001974 bool changed = false;
1975
1976 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1977 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
1978 changed = true;
1979 }
1980
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02001981 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
1982 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03001983 changed = true;
1984 }
1985
Johan Hedberg06199cf2012-02-22 16:37:11 +02001986 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
1987 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08001988 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001989
1990 if (changed)
1991 err = new_settings(hdev, sk);
1992
Johan Hedberg1de028c2012-02-29 19:55:35 -08001993 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001994 }
1995
Johan Hedberg4375f102013-09-25 13:26:10 +03001996 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
1997 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001998 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001999 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002000 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002001 }
2002
2003 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2004 if (!cmd) {
2005 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002006 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002007 }
2008
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002009 hci_req_init(&req, hdev);
2010
Johan Hedberg06199cf2012-02-22 16:37:11 +02002011 memset(&hci_cp, 0, sizeof(hci_cp));
2012
2013 if (val) {
2014 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002015 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002016 } else {
2017 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2018 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002019 }
2020
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002021 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2022 &hci_cp);
2023
2024 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302025 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002026 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002027
Johan Hedberg1de028c2012-02-29 19:55:35 -08002028unlock:
2029 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002030 return err;
2031}
2032
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002033/* This is a helper function to test for pending mgmt commands that can
2034 * cause CoD or EIR HCI commands. We can only allow one such pending
2035 * mgmt command at a time since otherwise we cannot easily track what
2036 * the current values are, will be, and based on that calculate if a new
2037 * HCI command needs to be sent and if yes with what value.
2038 */
2039static bool pending_eir_or_class(struct hci_dev *hdev)
2040{
2041 struct pending_cmd *cmd;
2042
2043 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2044 switch (cmd->opcode) {
2045 case MGMT_OP_ADD_UUID:
2046 case MGMT_OP_REMOVE_UUID:
2047 case MGMT_OP_SET_DEV_CLASS:
2048 case MGMT_OP_SET_POWERED:
2049 return true;
2050 }
2051 }
2052
2053 return false;
2054}
2055
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002056static const u8 bluetooth_base_uuid[] = {
2057 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2058 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2059};
2060
2061static u8 get_uuid_size(const u8 *uuid)
2062{
2063 u32 val;
2064
2065 if (memcmp(uuid, bluetooth_base_uuid, 12))
2066 return 128;
2067
2068 val = get_unaligned_le32(&uuid[12]);
2069 if (val > 0xffff)
2070 return 32;
2071
2072 return 16;
2073}
2074
Johan Hedberg92da6092013-03-15 17:06:55 -05002075static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2076{
2077 struct pending_cmd *cmd;
2078
2079 hci_dev_lock(hdev);
2080
2081 cmd = mgmt_pending_find(mgmt_op, hdev);
2082 if (!cmd)
2083 goto unlock;
2084
2085 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2086 hdev->dev_class, 3);
2087
2088 mgmt_pending_remove(cmd);
2089
2090unlock:
2091 hci_dev_unlock(hdev);
2092}
2093
2094static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2095{
2096 BT_DBG("status 0x%02x", status);
2097
2098 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2099}
2100
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002101static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002102{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002103 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002104 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002105 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002106 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002107 int err;
2108
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002109 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002110
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002111 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002112
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002113 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002114 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002115 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002116 goto failed;
2117 }
2118
Andre Guedes92c4c202012-06-07 19:05:44 -03002119 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002120 if (!uuid) {
2121 err = -ENOMEM;
2122 goto failed;
2123 }
2124
2125 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002126 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002127 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002128
Johan Hedbergde66aa62013-01-27 00:31:27 +02002129 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002130
Johan Hedberg890ea892013-03-15 17:06:52 -05002131 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002132
Johan Hedberg890ea892013-03-15 17:06:52 -05002133 update_class(&req);
2134 update_eir(&req);
2135
Johan Hedberg92da6092013-03-15 17:06:55 -05002136 err = hci_req_run(&req, add_uuid_complete);
2137 if (err < 0) {
2138 if (err != -ENODATA)
2139 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002141 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002142 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002143 goto failed;
2144 }
2145
2146 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002147 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002148 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002149 goto failed;
2150 }
2151
2152 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002153
2154failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002155 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002156 return err;
2157}
2158
Johan Hedberg24b78d02012-02-23 23:24:30 +02002159static bool enable_service_cache(struct hci_dev *hdev)
2160{
2161 if (!hdev_is_powered(hdev))
2162 return false;
2163
2164 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002165 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2166 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002167 return true;
2168 }
2169
2170 return false;
2171}
2172
Johan Hedberg92da6092013-03-15 17:06:55 -05002173static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2174{
2175 BT_DBG("status 0x%02x", status);
2176
2177 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2178}
2179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002180static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002181 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002182{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002183 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002184 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002185 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002186 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 -05002187 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002188 int err, found;
2189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002190 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002191
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002192 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002193
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002194 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002195 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002196 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002197 goto unlock;
2198 }
2199
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002200 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002201 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002202
Johan Hedberg24b78d02012-02-23 23:24:30 +02002203 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002204 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002205 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002206 goto unlock;
2207 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002208
Johan Hedberg9246a862012-02-23 21:33:16 +02002209 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002210 }
2211
2212 found = 0;
2213
Johan Hedberg056341c2013-01-27 00:31:30 +02002214 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002215 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2216 continue;
2217
2218 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002219 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002220 found++;
2221 }
2222
2223 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002224 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002225 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002226 goto unlock;
2227 }
2228
Johan Hedberg9246a862012-02-23 21:33:16 +02002229update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002230 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002231
Johan Hedberg890ea892013-03-15 17:06:52 -05002232 update_class(&req);
2233 update_eir(&req);
2234
Johan Hedberg92da6092013-03-15 17:06:55 -05002235 err = hci_req_run(&req, remove_uuid_complete);
2236 if (err < 0) {
2237 if (err != -ENODATA)
2238 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002241 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002242 goto unlock;
2243 }
2244
2245 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002246 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002247 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002248 goto unlock;
2249 }
2250
2251 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002252
2253unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002254 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002255 return err;
2256}
2257
Johan Hedberg92da6092013-03-15 17:06:55 -05002258static void set_class_complete(struct hci_dev *hdev, u8 status)
2259{
2260 BT_DBG("status 0x%02x", status);
2261
2262 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2263}
2264
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002265static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002266 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002267{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002268 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002269 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002270 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002271 int err;
2272
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002273 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002274
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002275 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002276 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2277 MGMT_STATUS_NOT_SUPPORTED);
2278
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002279 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002280
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002281 if (pending_eir_or_class(hdev)) {
2282 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2283 MGMT_STATUS_BUSY);
2284 goto unlock;
2285 }
2286
2287 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2288 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2289 MGMT_STATUS_INVALID_PARAMS);
2290 goto unlock;
2291 }
2292
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002293 hdev->major_class = cp->major;
2294 hdev->minor_class = cp->minor;
2295
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002296 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002297 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002298 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002299 goto unlock;
2300 }
2301
Johan Hedberg890ea892013-03-15 17:06:52 -05002302 hci_req_init(&req, hdev);
2303
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002304 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002305 hci_dev_unlock(hdev);
2306 cancel_delayed_work_sync(&hdev->service_cache);
2307 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002308 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002309 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002310
Johan Hedberg890ea892013-03-15 17:06:52 -05002311 update_class(&req);
2312
Johan Hedberg92da6092013-03-15 17:06:55 -05002313 err = hci_req_run(&req, set_class_complete);
2314 if (err < 0) {
2315 if (err != -ENODATA)
2316 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002317
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002318 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002319 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002320 goto unlock;
2321 }
2322
2323 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002324 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002325 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002326 goto unlock;
2327 }
2328
2329 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002330
Johan Hedbergb5235a62012-02-21 14:32:24 +02002331unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002332 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002333 return err;
2334}
2335
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002336static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002337 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002338{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002339 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002340 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002341 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002342 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002343
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002344 BT_DBG("request for %s", hdev->name);
2345
2346 if (!lmp_bredr_capable(hdev))
2347 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2348 MGMT_STATUS_NOT_SUPPORTED);
2349
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002350 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002351
Johan Hedberg86742e12011-11-07 23:13:38 +02002352 expected_len = sizeof(*cp) + key_count *
2353 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002354 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002355 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002356 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002357 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002358 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002359 }
2360
Johan Hedberg4ae14302013-01-20 14:27:13 +02002361 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2362 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2363 MGMT_STATUS_INVALID_PARAMS);
2364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002365 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002366 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002367
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002368 for (i = 0; i < key_count; i++) {
2369 struct mgmt_link_key_info *key = &cp->keys[i];
2370
Marcel Holtmann8e991132014-01-10 02:07:25 -08002371 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002372 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2373 MGMT_STATUS_INVALID_PARAMS);
2374 }
2375
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002376 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002377
2378 hci_link_keys_clear(hdev);
2379
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002380 if (cp->debug_keys)
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002381 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002382 else
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002383 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
2384
2385 if (changed)
2386 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002387
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002388 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002389 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002390
Johan Hedbergd753fdc2012-02-17 14:06:34 +02002391 hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002392 key->type, key->pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002393 }
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002396
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002397 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002398
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002399 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002400}
2401
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002402static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002403 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002404{
2405 struct mgmt_ev_device_unpaired ev;
2406
2407 bacpy(&ev.addr.bdaddr, bdaddr);
2408 ev.addr.type = addr_type;
2409
2410 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002411 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002412}
2413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002415 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002416{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002417 struct mgmt_cp_unpair_device *cp = data;
2418 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002419 struct hci_cp_disconnect dc;
2420 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002421 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002422 int err;
2423
Johan Hedberga8a1d192011-11-10 15:54:38 +02002424 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002425 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2426 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002427
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002428 if (!bdaddr_type_is_valid(cp->addr.type))
2429 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2430 MGMT_STATUS_INVALID_PARAMS,
2431 &rp, sizeof(rp));
2432
Johan Hedberg118da702013-01-20 14:27:20 +02002433 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2434 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2435 MGMT_STATUS_INVALID_PARAMS,
2436 &rp, sizeof(rp));
2437
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002438 hci_dev_lock(hdev);
2439
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002440 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002441 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002442 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002443 goto unlock;
2444 }
2445
Johan Hedberge0b2b272014-02-18 17:14:31 +02002446 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002447 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002448 } else {
2449 u8 addr_type;
2450
2451 if (cp->addr.type == BDADDR_LE_PUBLIC)
2452 addr_type = ADDR_LE_DEV_PUBLIC;
2453 else
2454 addr_type = ADDR_LE_DEV_RANDOM;
2455
Johan Hedberga7ec7332014-02-18 17:14:35 +02002456 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2457
Andre Guedesa9b0a042014-02-26 20:21:52 -03002458 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2459
Johan Hedberge0b2b272014-02-18 17:14:31 +02002460 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2461 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002462
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002463 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002464 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002465 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002466 goto unlock;
2467 }
2468
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002469 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002470 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002471 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002472 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002473 else
2474 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002476 } else {
2477 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002478 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002479
Johan Hedberga8a1d192011-11-10 15:54:38 +02002480 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002481 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002482 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002483 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002484 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002485 }
2486
Johan Hedberg124f6e32012-02-09 13:50:12 +02002487 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002488 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002489 if (!cmd) {
2490 err = -ENOMEM;
2491 goto unlock;
2492 }
2493
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002494 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002495 dc.reason = 0x13; /* Remote User Terminated Connection */
2496 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2497 if (err < 0)
2498 mgmt_pending_remove(cmd);
2499
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002500unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002501 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002502 return err;
2503}
2504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002505static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002506 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002507{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002508 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002509 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002510 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002511 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002512 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002513 int err;
2514
2515 BT_DBG("");
2516
Johan Hedberg06a63b12013-01-20 14:27:21 +02002517 memset(&rp, 0, sizeof(rp));
2518 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2519 rp.addr.type = cp->addr.type;
2520
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002521 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002522 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2523 MGMT_STATUS_INVALID_PARAMS,
2524 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002525
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002526 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002527
2528 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002529 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2530 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002531 goto failed;
2532 }
2533
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002534 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002535 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2536 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002537 goto failed;
2538 }
2539
Andre Guedes591f47f2012-04-24 21:02:49 -03002540 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002541 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2542 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002543 else
2544 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002545
Vishal Agarwalf9607272012-06-13 05:32:43 +05302546 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002547 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2548 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002549 goto failed;
2550 }
2551
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002552 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002553 if (!cmd) {
2554 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002555 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002556 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002557
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002558 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002559 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002560
2561 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2562 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002563 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002564
2565failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002566 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002567 return err;
2568}
2569
Andre Guedes57c14772012-04-24 21:02:50 -03002570static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002571{
2572 switch (link_type) {
2573 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002574 switch (addr_type) {
2575 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002576 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002577
Johan Hedberg48264f02011-11-09 13:58:58 +02002578 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002579 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002580 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002581 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002582
Johan Hedberg4c659c32011-11-07 23:13:39 +02002583 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002584 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002585 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002586 }
2587}
2588
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002589static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2590 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002591{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002592 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002593 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002594 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002595 int err;
2596 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002597
2598 BT_DBG("");
2599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002600 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002601
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002602 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002603 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002604 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002605 goto unlock;
2606 }
2607
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002608 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002609 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2610 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002611 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002612 }
2613
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002614 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002615 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002616 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002617 err = -ENOMEM;
2618 goto unlock;
2619 }
2620
Johan Hedberg2784eb42011-01-21 13:56:35 +02002621 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002622 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002623 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2624 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002625 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002626 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002627 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002628 continue;
2629 i++;
2630 }
2631
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002632 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002633
Johan Hedberg4c659c32011-11-07 23:13:39 +02002634 /* Recalculate length in case of filtered SCO connections, etc */
2635 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002636
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002637 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002638 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002639
Johan Hedberga38528f2011-01-22 06:46:43 +02002640 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002641
2642unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002643 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002644 return err;
2645}
2646
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002647static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002648 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002649{
2650 struct pending_cmd *cmd;
2651 int err;
2652
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002653 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002654 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002655 if (!cmd)
2656 return -ENOMEM;
2657
Johan Hedbergd8457692012-02-17 14:24:57 +02002658 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002659 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002660 if (err < 0)
2661 mgmt_pending_remove(cmd);
2662
2663 return err;
2664}
2665
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002666static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002667 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002668{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002669 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002670 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002671 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002672 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002673 int err;
2674
2675 BT_DBG("");
2676
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002677 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002678
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002679 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002680 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002681 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002682 goto failed;
2683 }
2684
Johan Hedbergd8457692012-02-17 14:24:57 +02002685 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002686 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002687 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002688 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002689 goto failed;
2690 }
2691
2692 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002693 struct mgmt_cp_pin_code_neg_reply ncp;
2694
2695 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002696
2697 BT_ERR("PIN code is not 16 bytes long");
2698
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002699 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002700 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002701 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002702 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002703
2704 goto failed;
2705 }
2706
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002707 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002708 if (!cmd) {
2709 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002710 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002711 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002712
Johan Hedbergd8457692012-02-17 14:24:57 +02002713 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002714 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002715 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002716
2717 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2718 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002719 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002720
2721failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002722 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002723 return err;
2724}
2725
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2727 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002728{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002729 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002730
2731 BT_DBG("");
2732
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002733 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002734
2735 hdev->io_capability = cp->io_capability;
2736
2737 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002738 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002739
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002740 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002741
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002742 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2743 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002744}
2745
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002746static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002747{
2748 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002749 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002750
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002751 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002752 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2753 continue;
2754
Johan Hedberge9a416b2011-02-19 12:05:56 -03002755 if (cmd->user_data != conn)
2756 continue;
2757
2758 return cmd;
2759 }
2760
2761 return NULL;
2762}
2763
2764static void pairing_complete(struct pending_cmd *cmd, u8 status)
2765{
2766 struct mgmt_rp_pair_device rp;
2767 struct hci_conn *conn = cmd->user_data;
2768
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002769 bacpy(&rp.addr.bdaddr, &conn->dst);
2770 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002771
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002772 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002773 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002774
2775 /* So we don't get further callbacks for this connection */
2776 conn->connect_cfm_cb = NULL;
2777 conn->security_cfm_cb = NULL;
2778 conn->disconn_cfm_cb = NULL;
2779
David Herrmann76a68ba2013-04-06 20:28:37 +02002780 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002781
Johan Hedberga664b5b2011-02-19 12:06:02 -03002782 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002783}
2784
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002785void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2786{
2787 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2788 struct pending_cmd *cmd;
2789
2790 cmd = find_pairing(conn);
2791 if (cmd)
2792 pairing_complete(cmd, status);
2793}
2794
Johan Hedberge9a416b2011-02-19 12:05:56 -03002795static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2796{
2797 struct pending_cmd *cmd;
2798
2799 BT_DBG("status %u", status);
2800
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002801 cmd = find_pairing(conn);
2802 if (!cmd)
2803 BT_DBG("Unable to find a pending command");
2804 else
Johan Hedberge2113262012-02-18 15:20:03 +02002805 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002806}
2807
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002808static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302809{
2810 struct pending_cmd *cmd;
2811
2812 BT_DBG("status %u", status);
2813
2814 if (!status)
2815 return;
2816
2817 cmd = find_pairing(conn);
2818 if (!cmd)
2819 BT_DBG("Unable to find a pending command");
2820 else
2821 pairing_complete(cmd, mgmt_status(status));
2822}
2823
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002824static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002825 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002826{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002827 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002828 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002829 struct pending_cmd *cmd;
2830 u8 sec_level, auth_type;
2831 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002832 int err;
2833
2834 BT_DBG("");
2835
Szymon Jancf950a30e2013-01-18 12:48:07 +01002836 memset(&rp, 0, sizeof(rp));
2837 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2838 rp.addr.type = cp->addr.type;
2839
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002840 if (!bdaddr_type_is_valid(cp->addr.type))
2841 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2842 MGMT_STATUS_INVALID_PARAMS,
2843 &rp, sizeof(rp));
2844
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002845 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002846
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002847 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002848 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2849 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002850 goto unlock;
2851 }
2852
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002853 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002854 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002855
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002856 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002857 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2858 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002859 } else {
2860 u8 addr_type;
2861
2862 /* Convert from L2CAP channel address type to HCI address type
2863 */
2864 if (cp->addr.type == BDADDR_LE_PUBLIC)
2865 addr_type = ADDR_LE_DEV_PUBLIC;
2866 else
2867 addr_type = ADDR_LE_DEV_RANDOM;
2868
2869 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002870 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002871 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002872
Ville Tervo30e76272011-02-22 16:10:53 -03002873 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002874 int status;
2875
2876 if (PTR_ERR(conn) == -EBUSY)
2877 status = MGMT_STATUS_BUSY;
2878 else
2879 status = MGMT_STATUS_CONNECT_FAILED;
2880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002881 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002882 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002883 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002884 goto unlock;
2885 }
2886
2887 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002888 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002889 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002890 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002891 goto unlock;
2892 }
2893
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002894 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002895 if (!cmd) {
2896 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002897 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002898 goto unlock;
2899 }
2900
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002901 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002902 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002903 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002904 conn->security_cfm_cb = pairing_complete_cb;
2905 conn->disconn_cfm_cb = pairing_complete_cb;
2906 } else {
2907 conn->connect_cfm_cb = le_pairing_complete_cb;
2908 conn->security_cfm_cb = le_pairing_complete_cb;
2909 conn->disconn_cfm_cb = le_pairing_complete_cb;
2910 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002911
Johan Hedberge9a416b2011-02-19 12:05:56 -03002912 conn->io_capability = cp->io_cap;
2913 cmd->user_data = conn;
2914
2915 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002916 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002917 pairing_complete(cmd, 0);
2918
2919 err = 0;
2920
2921unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002922 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002923 return err;
2924}
2925
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002926static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2927 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002928{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002929 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002930 struct pending_cmd *cmd;
2931 struct hci_conn *conn;
2932 int err;
2933
2934 BT_DBG("");
2935
Johan Hedberg28424702012-02-02 04:02:29 +02002936 hci_dev_lock(hdev);
2937
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002938 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002939 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002940 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002941 goto unlock;
2942 }
2943
Johan Hedberg28424702012-02-02 04:02:29 +02002944 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2945 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002946 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002947 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002948 goto unlock;
2949 }
2950
2951 conn = cmd->user_data;
2952
2953 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002954 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002955 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02002956 goto unlock;
2957 }
2958
2959 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
2960
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002961 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002962 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02002963unlock:
2964 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02002965 return err;
2966}
2967
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002968static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05002969 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002970 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03002971{
Johan Hedberga5c29682011-02-19 12:05:57 -03002972 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08002973 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03002974 int err;
2975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002976 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02002977
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002978 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002979 err = cmd_complete(sk, hdev->id, mgmt_op,
2980 MGMT_STATUS_NOT_POWERED, addr,
2981 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08002982 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03002983 }
2984
Johan Hedberg1707c602013-03-15 17:07:15 -05002985 if (addr->type == BDADDR_BREDR)
2986 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02002987 else
Johan Hedberg1707c602013-03-15 17:07:15 -05002988 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08002989
Johan Hedberg272d90d2012-02-09 15:26:12 +02002990 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05002991 err = cmd_complete(sk, hdev->id, mgmt_op,
2992 MGMT_STATUS_NOT_CONNECTED, addr,
2993 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02002994 goto done;
2995 }
2996
Johan Hedberg1707c602013-03-15 17:07:15 -05002997 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix47c15e22011-11-16 13:53:14 -08002998 /* Continue with pairing via SMP */
Brian Gix5fe57d92011-12-21 16:12:13 -08002999 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix47c15e22011-11-16 13:53:14 -08003000
Brian Gix5fe57d92011-12-21 16:12:13 -08003001 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003002 err = cmd_complete(sk, hdev->id, mgmt_op,
3003 MGMT_STATUS_SUCCESS, addr,
3004 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003005 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003006 err = cmd_complete(sk, hdev->id, mgmt_op,
3007 MGMT_STATUS_FAILED, addr,
3008 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003009
Brian Gix47c15e22011-11-16 13:53:14 -08003010 goto done;
3011 }
3012
Johan Hedberg1707c602013-03-15 17:07:15 -05003013 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003014 if (!cmd) {
3015 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003016 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003017 }
3018
Brian Gix0df4c182011-11-16 13:53:13 -08003019 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003020 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3021 struct hci_cp_user_passkey_reply cp;
3022
Johan Hedberg1707c602013-03-15 17:07:15 -05003023 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003024 cp.passkey = passkey;
3025 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3026 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003027 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3028 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003029
Johan Hedberga664b5b2011-02-19 12:06:02 -03003030 if (err < 0)
3031 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003032
Brian Gix0df4c182011-11-16 13:53:13 -08003033done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003034 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003035 return err;
3036}
3037
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303038static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3039 void *data, u16 len)
3040{
3041 struct mgmt_cp_pin_code_neg_reply *cp = data;
3042
3043 BT_DBG("");
3044
Johan Hedberg1707c602013-03-15 17:07:15 -05003045 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303046 MGMT_OP_PIN_CODE_NEG_REPLY,
3047 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3048}
3049
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003050static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3051 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003052{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003053 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003054
3055 BT_DBG("");
3056
3057 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003058 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003059 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003060
Johan Hedberg1707c602013-03-15 17:07:15 -05003061 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 MGMT_OP_USER_CONFIRM_REPLY,
3063 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003064}
3065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003066static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003067 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003068{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003069 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003070
3071 BT_DBG("");
3072
Johan Hedberg1707c602013-03-15 17:07:15 -05003073 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003074 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3075 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003076}
3077
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003078static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3079 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003080{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003081 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003082
3083 BT_DBG("");
3084
Johan Hedberg1707c602013-03-15 17:07:15 -05003085 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003086 MGMT_OP_USER_PASSKEY_REPLY,
3087 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003088}
3089
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003090static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003091 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003092{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003093 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003094
3095 BT_DBG("");
3096
Johan Hedberg1707c602013-03-15 17:07:15 -05003097 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003098 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3099 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003100}
3101
Johan Hedberg13928972013-03-15 17:07:00 -05003102static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003103{
Johan Hedberg13928972013-03-15 17:07:00 -05003104 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003105 struct hci_cp_write_local_name cp;
3106
Johan Hedberg13928972013-03-15 17:07:00 -05003107 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003108
Johan Hedberg890ea892013-03-15 17:06:52 -05003109 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003110}
3111
Johan Hedberg13928972013-03-15 17:07:00 -05003112static void set_name_complete(struct hci_dev *hdev, u8 status)
3113{
3114 struct mgmt_cp_set_local_name *cp;
3115 struct pending_cmd *cmd;
3116
3117 BT_DBG("status 0x%02x", status);
3118
3119 hci_dev_lock(hdev);
3120
3121 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3122 if (!cmd)
3123 goto unlock;
3124
3125 cp = cmd->param;
3126
3127 if (status)
3128 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3129 mgmt_status(status));
3130 else
3131 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3132 cp, sizeof(*cp));
3133
3134 mgmt_pending_remove(cmd);
3135
3136unlock:
3137 hci_dev_unlock(hdev);
3138}
3139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003140static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003141 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003142{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003143 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003144 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003145 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003146 int err;
3147
3148 BT_DBG("");
3149
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003150 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003151
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003152 /* If the old values are the same as the new ones just return a
3153 * direct command complete event.
3154 */
3155 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3156 !memcmp(hdev->short_name, cp->short_name,
3157 sizeof(hdev->short_name))) {
3158 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3159 data, len);
3160 goto failed;
3161 }
3162
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003163 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003164
Johan Hedbergb5235a62012-02-21 14:32:24 +02003165 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003166 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003167
3168 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003169 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003170 if (err < 0)
3171 goto failed;
3172
3173 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003174 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003175
Johan Hedbergb5235a62012-02-21 14:32:24 +02003176 goto failed;
3177 }
3178
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003179 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003180 if (!cmd) {
3181 err = -ENOMEM;
3182 goto failed;
3183 }
3184
Johan Hedberg13928972013-03-15 17:07:00 -05003185 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3186
Johan Hedberg890ea892013-03-15 17:06:52 -05003187 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003188
3189 if (lmp_bredr_capable(hdev)) {
3190 update_name(&req);
3191 update_eir(&req);
3192 }
3193
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003194 /* The name is stored in the scan response data and so
3195 * no need to udpate the advertising data here.
3196 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003197 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003198 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003199
Johan Hedberg13928972013-03-15 17:07:00 -05003200 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003201 if (err < 0)
3202 mgmt_pending_remove(cmd);
3203
3204failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003205 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003206 return err;
3207}
3208
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003209static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003210 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003211{
Szymon Jancc35938b2011-03-22 13:12:21 +01003212 struct pending_cmd *cmd;
3213 int err;
3214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003216
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003217 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003218
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003219 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003220 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003221 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003222 goto unlock;
3223 }
3224
Andre Guedes9a1a1992012-07-24 15:03:48 -03003225 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003226 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003227 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003228 goto unlock;
3229 }
3230
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003231 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003232 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003233 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003234 goto unlock;
3235 }
3236
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003237 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003238 if (!cmd) {
3239 err = -ENOMEM;
3240 goto unlock;
3241 }
3242
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003243 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3244 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3245 0, NULL);
3246 else
3247 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3248
Szymon Jancc35938b2011-03-22 13:12:21 +01003249 if (err < 0)
3250 mgmt_pending_remove(cmd);
3251
3252unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003253 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003254 return err;
3255}
3256
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003257static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003258 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003259{
Szymon Janc2763eda2011-03-22 13:12:22 +01003260 int err;
3261
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003262 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003263
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003264 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003265
Marcel Holtmannec109112014-01-10 02:07:30 -08003266 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3267 struct mgmt_cp_add_remote_oob_data *cp = data;
3268 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003269
Marcel Holtmannec109112014-01-10 02:07:30 -08003270 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3271 cp->hash, cp->randomizer);
3272 if (err < 0)
3273 status = MGMT_STATUS_FAILED;
3274 else
3275 status = MGMT_STATUS_SUCCESS;
3276
3277 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3278 status, &cp->addr, sizeof(cp->addr));
3279 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3280 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3281 u8 status;
3282
3283 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3284 cp->hash192,
3285 cp->randomizer192,
3286 cp->hash256,
3287 cp->randomizer256);
3288 if (err < 0)
3289 status = MGMT_STATUS_FAILED;
3290 else
3291 status = MGMT_STATUS_SUCCESS;
3292
3293 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3294 status, &cp->addr, sizeof(cp->addr));
3295 } else {
3296 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3297 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3298 MGMT_STATUS_INVALID_PARAMS);
3299 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003300
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003301 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003302 return err;
3303}
3304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003306 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003307{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003308 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003309 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003310 int err;
3311
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003312 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003313
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003314 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003315
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003316 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003317 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003318 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003319 else
Szymon Janca6785be2012-12-13 15:11:21 +01003320 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003322 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003323 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003324
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003325 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003326 return err;
3327}
3328
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003329static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3330{
3331 struct pending_cmd *cmd;
3332 u8 type;
3333 int err;
3334
3335 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3336
3337 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3338 if (!cmd)
3339 return -ENOENT;
3340
3341 type = hdev->discovery.type;
3342
3343 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3344 &type, sizeof(type));
3345 mgmt_pending_remove(cmd);
3346
3347 return err;
3348}
3349
Andre Guedes7c307722013-04-30 15:29:28 -03003350static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3351{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003352 unsigned long timeout = 0;
3353
Andre Guedes7c307722013-04-30 15:29:28 -03003354 BT_DBG("status %d", status);
3355
3356 if (status) {
3357 hci_dev_lock(hdev);
3358 mgmt_start_discovery_failed(hdev, status);
3359 hci_dev_unlock(hdev);
3360 return;
3361 }
3362
3363 hci_dev_lock(hdev);
3364 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3365 hci_dev_unlock(hdev);
3366
3367 switch (hdev->discovery.type) {
3368 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003369 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003370 break;
3371
3372 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003373 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003374 break;
3375
3376 case DISCOV_TYPE_BREDR:
3377 break;
3378
3379 default:
3380 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3381 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003382
3383 if (!timeout)
3384 return;
3385
3386 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003387}
3388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003389static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003390 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003391{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003392 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003393 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003394 struct hci_cp_le_set_scan_param param_cp;
3395 struct hci_cp_le_set_scan_enable enable_cp;
3396 struct hci_cp_inquiry inq_cp;
3397 struct hci_request req;
3398 /* General inquiry access code (GIAC) */
3399 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003400 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003401 int err;
3402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003403 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003405 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003406
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003407 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003408 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003410 goto failed;
3411 }
3412
Andre Guedes642be6c2012-03-21 00:03:37 -03003413 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3414 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3415 MGMT_STATUS_BUSY);
3416 goto failed;
3417 }
3418
Johan Hedbergff9ef572012-01-04 14:23:45 +02003419 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003420 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003422 goto failed;
3423 }
3424
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003425 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003426 if (!cmd) {
3427 err = -ENOMEM;
3428 goto failed;
3429 }
3430
Andre Guedes4aab14e2012-02-17 20:39:36 -03003431 hdev->discovery.type = cp->type;
3432
Andre Guedes7c307722013-04-30 15:29:28 -03003433 hci_req_init(&req, hdev);
3434
Andre Guedes4aab14e2012-02-17 20:39:36 -03003435 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003436 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003437 status = mgmt_bredr_support(hdev);
3438 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003439 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003440 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003441 mgmt_pending_remove(cmd);
3442 goto failed;
3443 }
3444
Andre Guedes7c307722013-04-30 15:29:28 -03003445 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3446 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3447 MGMT_STATUS_BUSY);
3448 mgmt_pending_remove(cmd);
3449 goto failed;
3450 }
3451
3452 hci_inquiry_cache_flush(hdev);
3453
3454 memset(&inq_cp, 0, sizeof(inq_cp));
3455 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003456 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003457 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003458 break;
3459
3460 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003461 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003462 status = mgmt_le_support(hdev);
3463 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003464 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003465 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003466 mgmt_pending_remove(cmd);
3467 goto failed;
3468 }
3469
Andre Guedes7c307722013-04-30 15:29:28 -03003470 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003471 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003472 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3473 MGMT_STATUS_NOT_SUPPORTED);
3474 mgmt_pending_remove(cmd);
3475 goto failed;
3476 }
3477
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003478 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003479 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3480 MGMT_STATUS_REJECTED);
3481 mgmt_pending_remove(cmd);
3482 goto failed;
3483 }
3484
Andre Guedesc54c3862014-02-26 20:21:50 -03003485 /* If controller is scanning, it means the background scanning
3486 * is running. Thus, we should temporarily stop it in order to
3487 * set the discovery scanning parameters.
3488 */
3489 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3490 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003491
3492 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003493
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003494 /* All active scans will be done with either a resolvable
3495 * private address (when privacy feature has been enabled)
3496 * or unresolvable private address.
3497 */
3498 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003499 if (err < 0) {
3500 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3501 MGMT_STATUS_FAILED);
3502 mgmt_pending_remove(cmd);
3503 goto failed;
3504 }
3505
Andre Guedes7c307722013-04-30 15:29:28 -03003506 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003507 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3508 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003509 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003510 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3511 &param_cp);
3512
3513 memset(&enable_cp, 0, sizeof(enable_cp));
3514 enable_cp.enable = LE_SCAN_ENABLE;
3515 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3516 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3517 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003518 break;
3519
Andre Guedesf39799f2012-02-17 20:39:35 -03003520 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003521 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3522 MGMT_STATUS_INVALID_PARAMS);
3523 mgmt_pending_remove(cmd);
3524 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003525 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003526
Andre Guedes7c307722013-04-30 15:29:28 -03003527 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003528 if (err < 0)
3529 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003530 else
3531 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003532
3533failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003534 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003535 return err;
3536}
3537
Andre Guedes1183fdc2013-04-30 15:29:35 -03003538static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3539{
3540 struct pending_cmd *cmd;
3541 int err;
3542
3543 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3544 if (!cmd)
3545 return -ENOENT;
3546
3547 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3548 &hdev->discovery.type, sizeof(hdev->discovery.type));
3549 mgmt_pending_remove(cmd);
3550
3551 return err;
3552}
3553
Andre Guedes0e05bba2013-04-30 15:29:33 -03003554static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3555{
3556 BT_DBG("status %d", status);
3557
3558 hci_dev_lock(hdev);
3559
3560 if (status) {
3561 mgmt_stop_discovery_failed(hdev, status);
3562 goto unlock;
3563 }
3564
3565 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3566
3567unlock:
3568 hci_dev_unlock(hdev);
3569}
3570
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003571static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003572 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003573{
Johan Hedbergd9306502012-02-20 23:25:18 +02003574 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003575 struct pending_cmd *cmd;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003576 struct hci_cp_remote_name_req_cancel cp;
3577 struct inquiry_entry *e;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003578 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003579 int err;
3580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003582
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003583 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003584
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003585 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003586 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003587 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3588 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003589 goto unlock;
3590 }
3591
3592 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003593 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003594 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3595 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003596 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003597 }
3598
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003599 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003600 if (!cmd) {
3601 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003602 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003603 }
3604
Andre Guedes0e05bba2013-04-30 15:29:33 -03003605 hci_req_init(&req, hdev);
3606
Andre Guedese0d9727e2012-03-20 15:15:36 -03003607 switch (hdev->discovery.state) {
3608 case DISCOVERY_FINDING:
Andre Guedes0e05bba2013-04-30 15:29:33 -03003609 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3610 hci_req_add(&req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
3611 } else {
3612 cancel_delayed_work(&hdev->le_scan_disable);
3613
Andre Guedesb1efcc22014-02-26 20:21:40 -03003614 hci_req_add_le_scan_disable(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003615 }
Andre Guedesc9ecc482012-03-15 16:52:08 -03003616
Andre Guedese0d9727e2012-03-20 15:15:36 -03003617 break;
3618
3619 case DISCOVERY_RESOLVING:
3620 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003621 NAME_PENDING);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003622 if (!e) {
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003623 mgmt_pending_remove(cmd);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003624 err = cmd_complete(sk, hdev->id,
3625 MGMT_OP_STOP_DISCOVERY, 0,
3626 &mgmt_cp->type,
3627 sizeof(mgmt_cp->type));
3628 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3629 goto unlock;
3630 }
3631
3632 bacpy(&cp.bdaddr, &e->data.bdaddr);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003633 hci_req_add(&req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
3634 &cp);
Andre Guedese0d9727e2012-03-20 15:15:36 -03003635
3636 break;
3637
3638 default:
3639 BT_DBG("unknown discovery state %u", hdev->discovery.state);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003640
3641 mgmt_pending_remove(cmd);
3642 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
3643 MGMT_STATUS_FAILED, &mgmt_cp->type,
3644 sizeof(mgmt_cp->type));
3645 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003646 }
3647
Andre Guedes0e05bba2013-04-30 15:29:33 -03003648 err = hci_req_run(&req, stop_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003649 if (err < 0)
3650 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003651 else
3652 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003653
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003654unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003655 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003656 return err;
3657}
3658
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003659static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003661{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003662 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003663 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003664 int err;
3665
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003666 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003667
Johan Hedberg561aafb2012-01-04 13:31:59 +02003668 hci_dev_lock(hdev);
3669
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003670 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003671 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3672 MGMT_STATUS_FAILED, &cp->addr,
3673 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003674 goto failed;
3675 }
3676
Johan Hedberga198e7b2012-02-17 14:27:06 +02003677 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003678 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003679 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3680 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3681 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003682 goto failed;
3683 }
3684
3685 if (cp->name_known) {
3686 e->name_state = NAME_KNOWN;
3687 list_del(&e->list);
3688 } else {
3689 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003690 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003691 }
3692
Johan Hedberge3846622013-01-09 15:29:33 +02003693 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3694 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003695
3696failed:
3697 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003698 return err;
3699}
3700
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003701static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003702 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003703{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003704 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003705 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003706 int err;
3707
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003708 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003709
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003710 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003711 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3712 MGMT_STATUS_INVALID_PARAMS,
3713 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003714
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003715 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003716
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003717 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003718 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003719 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003720 else
Szymon Janca6785be2012-12-13 15:11:21 +01003721 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003722
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003723 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003724 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003725
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003726 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003727
3728 return err;
3729}
3730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003731static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003732 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003733{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003734 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003735 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003736 int err;
3737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003738 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003739
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003740 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003741 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3742 MGMT_STATUS_INVALID_PARAMS,
3743 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003744
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003745 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003746
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003747 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003748 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003749 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003750 else
Szymon Janca6785be2012-12-13 15:11:21 +01003751 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003752
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003753 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003754 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003755
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003756 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003757
3758 return err;
3759}
3760
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003761static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3762 u16 len)
3763{
3764 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003765 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003766 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003767 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003768
3769 BT_DBG("%s", hdev->name);
3770
Szymon Jancc72d4b82012-03-16 16:02:57 +01003771 source = __le16_to_cpu(cp->source);
3772
3773 if (source > 0x0002)
3774 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3775 MGMT_STATUS_INVALID_PARAMS);
3776
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003777 hci_dev_lock(hdev);
3778
Szymon Jancc72d4b82012-03-16 16:02:57 +01003779 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003780 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3781 hdev->devid_product = __le16_to_cpu(cp->product);
3782 hdev->devid_version = __le16_to_cpu(cp->version);
3783
3784 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3785
Johan Hedberg890ea892013-03-15 17:06:52 -05003786 hci_req_init(&req, hdev);
3787 update_eir(&req);
3788 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003789
3790 hci_dev_unlock(hdev);
3791
3792 return err;
3793}
3794
Johan Hedberg4375f102013-09-25 13:26:10 +03003795static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3796{
3797 struct cmd_lookup match = { NULL, hdev };
3798
3799 if (status) {
3800 u8 mgmt_err = mgmt_status(status);
3801
3802 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3803 cmd_status_rsp, &mgmt_err);
3804 return;
3805 }
3806
3807 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3808 &match);
3809
3810 new_settings(hdev, match.sk);
3811
3812 if (match.sk)
3813 sock_put(match.sk);
3814}
3815
Marcel Holtmann21b51872013-10-10 09:47:53 -07003816static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3817 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003818{
3819 struct mgmt_mode *cp = data;
3820 struct pending_cmd *cmd;
3821 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003822 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003823 int err;
3824
3825 BT_DBG("request for %s", hdev->name);
3826
Johan Hedberge6fe7982013-10-02 15:45:22 +03003827 status = mgmt_le_support(hdev);
3828 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003829 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003830 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003831
3832 if (cp->val != 0x00 && cp->val != 0x01)
3833 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3834 MGMT_STATUS_INVALID_PARAMS);
3835
3836 hci_dev_lock(hdev);
3837
3838 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003839 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003840
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003841 /* The following conditions are ones which mean that we should
3842 * not do any HCI communication but directly send a mgmt
3843 * response to user space (after toggling the flag if
3844 * necessary).
3845 */
3846 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003847 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003848 bool changed = false;
3849
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003850 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3851 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003852 changed = true;
3853 }
3854
3855 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3856 if (err < 0)
3857 goto unlock;
3858
3859 if (changed)
3860 err = new_settings(hdev, sk);
3861
3862 goto unlock;
3863 }
3864
3865 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3866 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3867 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3868 MGMT_STATUS_BUSY);
3869 goto unlock;
3870 }
3871
3872 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3873 if (!cmd) {
3874 err = -ENOMEM;
3875 goto unlock;
3876 }
3877
3878 hci_req_init(&req, hdev);
3879
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003880 if (val)
3881 enable_advertising(&req);
3882 else
3883 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003884
3885 err = hci_req_run(&req, set_advertising_complete);
3886 if (err < 0)
3887 mgmt_pending_remove(cmd);
3888
3889unlock:
3890 hci_dev_unlock(hdev);
3891 return err;
3892}
3893
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003894static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3895 void *data, u16 len)
3896{
3897 struct mgmt_cp_set_static_address *cp = data;
3898 int err;
3899
3900 BT_DBG("%s", hdev->name);
3901
Marcel Holtmann62af4442013-10-02 22:10:32 -07003902 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003903 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003904 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003905
3906 if (hdev_is_powered(hdev))
3907 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3908 MGMT_STATUS_REJECTED);
3909
3910 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3911 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3912 return cmd_status(sk, hdev->id,
3913 MGMT_OP_SET_STATIC_ADDRESS,
3914 MGMT_STATUS_INVALID_PARAMS);
3915
3916 /* Two most significant bits shall be set */
3917 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3918 return cmd_status(sk, hdev->id,
3919 MGMT_OP_SET_STATIC_ADDRESS,
3920 MGMT_STATUS_INVALID_PARAMS);
3921 }
3922
3923 hci_dev_lock(hdev);
3924
3925 bacpy(&hdev->static_addr, &cp->bdaddr);
3926
3927 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3928
3929 hci_dev_unlock(hdev);
3930
3931 return err;
3932}
3933
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003934static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3935 void *data, u16 len)
3936{
3937 struct mgmt_cp_set_scan_params *cp = data;
3938 __u16 interval, window;
3939 int err;
3940
3941 BT_DBG("%s", hdev->name);
3942
3943 if (!lmp_le_capable(hdev))
3944 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3945 MGMT_STATUS_NOT_SUPPORTED);
3946
3947 interval = __le16_to_cpu(cp->interval);
3948
3949 if (interval < 0x0004 || interval > 0x4000)
3950 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3951 MGMT_STATUS_INVALID_PARAMS);
3952
3953 window = __le16_to_cpu(cp->window);
3954
3955 if (window < 0x0004 || window > 0x4000)
3956 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3957 MGMT_STATUS_INVALID_PARAMS);
3958
Marcel Holtmann899e1072013-10-14 09:55:32 -07003959 if (window > interval)
3960 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3961 MGMT_STATUS_INVALID_PARAMS);
3962
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003963 hci_dev_lock(hdev);
3964
3965 hdev->le_scan_interval = interval;
3966 hdev->le_scan_window = window;
3967
3968 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3969
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003970 /* If background scan is running, restart it so new parameters are
3971 * loaded.
3972 */
3973 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
3974 hdev->discovery.state == DISCOVERY_STOPPED) {
3975 struct hci_request req;
3976
3977 hci_req_init(&req, hdev);
3978
3979 hci_req_add_le_scan_disable(&req);
3980 hci_req_add_le_passive_scan(&req);
3981
3982 hci_req_run(&req, NULL);
3983 }
3984
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003985 hci_dev_unlock(hdev);
3986
3987 return err;
3988}
3989
Johan Hedberg33e38b32013-03-15 17:07:05 -05003990static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
3991{
3992 struct pending_cmd *cmd;
3993
3994 BT_DBG("status 0x%02x", status);
3995
3996 hci_dev_lock(hdev);
3997
3998 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
3999 if (!cmd)
4000 goto unlock;
4001
4002 if (status) {
4003 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4004 mgmt_status(status));
4005 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004006 struct mgmt_mode *cp = cmd->param;
4007
4008 if (cp->val)
4009 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4010 else
4011 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4012
Johan Hedberg33e38b32013-03-15 17:07:05 -05004013 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4014 new_settings(hdev, cmd->sk);
4015 }
4016
4017 mgmt_pending_remove(cmd);
4018
4019unlock:
4020 hci_dev_unlock(hdev);
4021}
4022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004023static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004024 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004025{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004026 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004027 struct pending_cmd *cmd;
4028 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004029 int err;
4030
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004031 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004032
Johan Hedberg56f87902013-10-02 13:43:13 +03004033 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4034 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004035 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4036 MGMT_STATUS_NOT_SUPPORTED);
4037
Johan Hedberga7e80f22013-01-09 16:05:19 +02004038 if (cp->val != 0x00 && cp->val != 0x01)
4039 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4040 MGMT_STATUS_INVALID_PARAMS);
4041
Johan Hedberg5400c042012-02-21 16:40:33 +02004042 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004043 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004044 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004045
4046 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004047 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004048 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004049
4050 hci_dev_lock(hdev);
4051
Johan Hedberg05cbf292013-03-15 17:07:07 -05004052 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4053 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4054 MGMT_STATUS_BUSY);
4055 goto unlock;
4056 }
4057
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004058 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4059 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4060 hdev);
4061 goto unlock;
4062 }
4063
Johan Hedberg33e38b32013-03-15 17:07:05 -05004064 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4065 data, len);
4066 if (!cmd) {
4067 err = -ENOMEM;
4068 goto unlock;
4069 }
4070
4071 hci_req_init(&req, hdev);
4072
Johan Hedberg406d7802013-03-15 17:07:09 -05004073 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004074
4075 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004076 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004077 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004078 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004079 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004080 }
4081
Johan Hedberg33e38b32013-03-15 17:07:05 -05004082unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004083 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004084
Antti Julkuf6422ec2011-06-22 13:11:56 +03004085 return err;
4086}
4087
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004088static void set_bredr_scan(struct hci_request *req)
4089{
4090 struct hci_dev *hdev = req->hdev;
4091 u8 scan = 0;
4092
4093 /* Ensure that fast connectable is disabled. This function will
4094 * not do anything if the page scan parameters are already what
4095 * they should be.
4096 */
4097 write_fast_connectable(req, false);
4098
4099 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4100 scan |= SCAN_PAGE;
4101 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4102 scan |= SCAN_INQUIRY;
4103
4104 if (scan)
4105 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4106}
4107
Johan Hedberg0663ca22013-10-02 13:43:14 +03004108static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4109{
4110 struct pending_cmd *cmd;
4111
4112 BT_DBG("status 0x%02x", status);
4113
4114 hci_dev_lock(hdev);
4115
4116 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4117 if (!cmd)
4118 goto unlock;
4119
4120 if (status) {
4121 u8 mgmt_err = mgmt_status(status);
4122
4123 /* We need to restore the flag if related HCI commands
4124 * failed.
4125 */
4126 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4127
4128 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4129 } else {
4130 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4131 new_settings(hdev, cmd->sk);
4132 }
4133
4134 mgmt_pending_remove(cmd);
4135
4136unlock:
4137 hci_dev_unlock(hdev);
4138}
4139
4140static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4141{
4142 struct mgmt_mode *cp = data;
4143 struct pending_cmd *cmd;
4144 struct hci_request req;
4145 int err;
4146
4147 BT_DBG("request for %s", hdev->name);
4148
4149 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4150 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4151 MGMT_STATUS_NOT_SUPPORTED);
4152
4153 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4154 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4155 MGMT_STATUS_REJECTED);
4156
4157 if (cp->val != 0x00 && cp->val != 0x01)
4158 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4159 MGMT_STATUS_INVALID_PARAMS);
4160
4161 hci_dev_lock(hdev);
4162
4163 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4164 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4165 goto unlock;
4166 }
4167
4168 if (!hdev_is_powered(hdev)) {
4169 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004170 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4171 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4172 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4173 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4174 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4175 }
4176
4177 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4178
4179 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4180 if (err < 0)
4181 goto unlock;
4182
4183 err = new_settings(hdev, sk);
4184 goto unlock;
4185 }
4186
4187 /* Reject disabling when powered on */
4188 if (!cp->val) {
4189 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4190 MGMT_STATUS_REJECTED);
4191 goto unlock;
4192 }
4193
4194 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4195 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4196 MGMT_STATUS_BUSY);
4197 goto unlock;
4198 }
4199
4200 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4201 if (!cmd) {
4202 err = -ENOMEM;
4203 goto unlock;
4204 }
4205
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004206 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004207 * generates the correct flags.
4208 */
4209 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4210
4211 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004212
4213 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4214 set_bredr_scan(&req);
4215
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004216 /* Since only the advertising data flags will change, there
4217 * is no need to update the scan response data.
4218 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004219 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004220
Johan Hedberg0663ca22013-10-02 13:43:14 +03004221 err = hci_req_run(&req, set_bredr_complete);
4222 if (err < 0)
4223 mgmt_pending_remove(cmd);
4224
4225unlock:
4226 hci_dev_unlock(hdev);
4227 return err;
4228}
4229
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004230static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4231 void *data, u16 len)
4232{
4233 struct mgmt_mode *cp = data;
4234 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004235 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004236 int err;
4237
4238 BT_DBG("request for %s", hdev->name);
4239
4240 status = mgmt_bredr_support(hdev);
4241 if (status)
4242 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4243 status);
4244
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004245 if (!lmp_sc_capable(hdev) &&
4246 !test_bit(HCI_FORCE_SC, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004247 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4248 MGMT_STATUS_NOT_SUPPORTED);
4249
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004250 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004251 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4252 MGMT_STATUS_INVALID_PARAMS);
4253
4254 hci_dev_lock(hdev);
4255
4256 if (!hdev_is_powered(hdev)) {
4257 bool changed;
4258
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004259 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004260 changed = !test_and_set_bit(HCI_SC_ENABLED,
4261 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004262 if (cp->val == 0x02)
4263 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4264 else
4265 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4266 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004267 changed = test_and_clear_bit(HCI_SC_ENABLED,
4268 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004269 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4270 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004271
4272 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4273 if (err < 0)
4274 goto failed;
4275
4276 if (changed)
4277 err = new_settings(hdev, sk);
4278
4279 goto failed;
4280 }
4281
4282 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4283 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4284 MGMT_STATUS_BUSY);
4285 goto failed;
4286 }
4287
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004288 val = !!cp->val;
4289
4290 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4291 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004292 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4293 goto failed;
4294 }
4295
4296 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4297 if (!cmd) {
4298 err = -ENOMEM;
4299 goto failed;
4300 }
4301
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004302 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004303 if (err < 0) {
4304 mgmt_pending_remove(cmd);
4305 goto failed;
4306 }
4307
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004308 if (cp->val == 0x02)
4309 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4310 else
4311 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4312
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004313failed:
4314 hci_dev_unlock(hdev);
4315 return err;
4316}
4317
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004318static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4319 void *data, u16 len)
4320{
4321 struct mgmt_mode *cp = data;
4322 bool changed;
4323 int err;
4324
4325 BT_DBG("request for %s", hdev->name);
4326
4327 if (cp->val != 0x00 && cp->val != 0x01)
4328 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4329 MGMT_STATUS_INVALID_PARAMS);
4330
4331 hci_dev_lock(hdev);
4332
4333 if (cp->val)
4334 changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4335 else
4336 changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags);
4337
4338 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4339 if (err < 0)
4340 goto unlock;
4341
4342 if (changed)
4343 err = new_settings(hdev, sk);
4344
4345unlock:
4346 hci_dev_unlock(hdev);
4347 return err;
4348}
4349
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004350static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4351 u16 len)
4352{
4353 struct mgmt_cp_set_privacy *cp = cp_data;
4354 bool changed;
4355 int err;
4356
4357 BT_DBG("request for %s", hdev->name);
4358
4359 if (!lmp_le_capable(hdev))
4360 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4361 MGMT_STATUS_NOT_SUPPORTED);
4362
4363 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4364 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4365 MGMT_STATUS_INVALID_PARAMS);
4366
4367 if (hdev_is_powered(hdev))
4368 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4369 MGMT_STATUS_REJECTED);
4370
4371 hci_dev_lock(hdev);
4372
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004373 /* If user space supports this command it is also expected to
4374 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4375 */
4376 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4377
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004378 if (cp->privacy) {
4379 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4380 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4381 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4382 } else {
4383 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4384 memset(hdev->irk, 0, sizeof(hdev->irk));
4385 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4386 }
4387
4388 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4389 if (err < 0)
4390 goto unlock;
4391
4392 if (changed)
4393 err = new_settings(hdev, sk);
4394
4395unlock:
4396 hci_dev_unlock(hdev);
4397 return err;
4398}
4399
Johan Hedberg41edf162014-02-18 10:19:35 +02004400static bool irk_is_valid(struct mgmt_irk_info *irk)
4401{
4402 switch (irk->addr.type) {
4403 case BDADDR_LE_PUBLIC:
4404 return true;
4405
4406 case BDADDR_LE_RANDOM:
4407 /* Two most significant bits shall be set */
4408 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4409 return false;
4410 return true;
4411 }
4412
4413 return false;
4414}
4415
4416static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4417 u16 len)
4418{
4419 struct mgmt_cp_load_irks *cp = cp_data;
4420 u16 irk_count, expected_len;
4421 int i, err;
4422
4423 BT_DBG("request for %s", hdev->name);
4424
4425 if (!lmp_le_capable(hdev))
4426 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4427 MGMT_STATUS_NOT_SUPPORTED);
4428
4429 irk_count = __le16_to_cpu(cp->irk_count);
4430
4431 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4432 if (expected_len != len) {
4433 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004434 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004435 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4436 MGMT_STATUS_INVALID_PARAMS);
4437 }
4438
4439 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4440
4441 for (i = 0; i < irk_count; i++) {
4442 struct mgmt_irk_info *key = &cp->irks[i];
4443
4444 if (!irk_is_valid(key))
4445 return cmd_status(sk, hdev->id,
4446 MGMT_OP_LOAD_IRKS,
4447 MGMT_STATUS_INVALID_PARAMS);
4448 }
4449
4450 hci_dev_lock(hdev);
4451
4452 hci_smp_irks_clear(hdev);
4453
4454 for (i = 0; i < irk_count; i++) {
4455 struct mgmt_irk_info *irk = &cp->irks[i];
4456 u8 addr_type;
4457
4458 if (irk->addr.type == BDADDR_LE_PUBLIC)
4459 addr_type = ADDR_LE_DEV_PUBLIC;
4460 else
4461 addr_type = ADDR_LE_DEV_RANDOM;
4462
4463 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4464 BDADDR_ANY);
4465 }
4466
4467 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4468
4469 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4470
4471 hci_dev_unlock(hdev);
4472
4473 return err;
4474}
4475
Johan Hedberg3f706b72013-01-20 14:27:16 +02004476static bool ltk_is_valid(struct mgmt_ltk_info *key)
4477{
4478 if (key->master != 0x00 && key->master != 0x01)
4479 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004480
4481 switch (key->addr.type) {
4482 case BDADDR_LE_PUBLIC:
4483 return true;
4484
4485 case BDADDR_LE_RANDOM:
4486 /* Two most significant bits shall be set */
4487 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4488 return false;
4489 return true;
4490 }
4491
4492 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004493}
4494
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004495static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004496 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004497{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004498 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4499 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004500 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004501
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004502 BT_DBG("request for %s", hdev->name);
4503
4504 if (!lmp_le_capable(hdev))
4505 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4506 MGMT_STATUS_NOT_SUPPORTED);
4507
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004508 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004509
4510 expected_len = sizeof(*cp) + key_count *
4511 sizeof(struct mgmt_ltk_info);
4512 if (expected_len != len) {
4513 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004514 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004515 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004516 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004517 }
4518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004519 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004520
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004521 for (i = 0; i < key_count; i++) {
4522 struct mgmt_ltk_info *key = &cp->keys[i];
4523
Johan Hedberg3f706b72013-01-20 14:27:16 +02004524 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004525 return cmd_status(sk, hdev->id,
4526 MGMT_OP_LOAD_LONG_TERM_KEYS,
4527 MGMT_STATUS_INVALID_PARAMS);
4528 }
4529
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004530 hci_dev_lock(hdev);
4531
4532 hci_smp_ltks_clear(hdev);
4533
4534 for (i = 0; i < key_count; i++) {
4535 struct mgmt_ltk_info *key = &cp->keys[i];
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004536 u8 type, addr_type;
4537
4538 if (key->addr.type == BDADDR_LE_PUBLIC)
4539 addr_type = ADDR_LE_DEV_PUBLIC;
4540 else
4541 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004542
4543 if (key->master)
4544 type = HCI_SMP_LTK;
4545 else
4546 type = HCI_SMP_LTK_SLAVE;
4547
Johan Hedberg35d70272014-02-19 14:57:47 +02004548 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
4549 key->type, key->val, key->enc_size, key->ediv,
4550 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004551 }
4552
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004553 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4554 NULL, 0);
4555
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004556 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004557
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004558 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004559}
4560
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004561struct cmd_conn_lookup {
4562 struct hci_conn *conn;
4563 bool valid_tx_power;
4564 u8 mgmt_status;
4565};
4566
4567static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4568{
4569 struct cmd_conn_lookup *match = data;
4570 struct mgmt_cp_get_conn_info *cp;
4571 struct mgmt_rp_get_conn_info rp;
4572 struct hci_conn *conn = cmd->user_data;
4573
4574 if (conn != match->conn)
4575 return;
4576
4577 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4578
4579 memset(&rp, 0, sizeof(rp));
4580 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4581 rp.addr.type = cp->addr.type;
4582
4583 if (!match->mgmt_status) {
4584 rp.rssi = conn->rssi;
4585
4586 if (match->valid_tx_power)
4587 rp.tx_power = conn->tx_power;
4588 else
4589 rp.tx_power = HCI_TX_POWER_INVALID;
4590
4591 rp.max_tx_power = HCI_TX_POWER_INVALID;
4592 }
4593
4594 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4595 match->mgmt_status, &rp, sizeof(rp));
4596
4597 hci_conn_drop(conn);
4598
4599 mgmt_pending_remove(cmd);
4600}
4601
4602static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4603{
4604 struct hci_cp_read_rssi *cp;
4605 struct hci_conn *conn;
4606 struct cmd_conn_lookup match;
4607 u16 handle;
4608
4609 BT_DBG("status 0x%02x", status);
4610
4611 hci_dev_lock(hdev);
4612
4613 /* TX power data is valid in case request completed successfully,
4614 * otherwise we assume it's not valid.
4615 */
4616 match.valid_tx_power = !status;
4617
4618 /* Commands sent in request are either Read RSSI or Read Transmit Power
4619 * Level so we check which one was last sent to retrieve connection
4620 * handle. Both commands have handle as first parameter so it's safe to
4621 * cast data on the same command struct.
4622 *
4623 * First command sent is always Read RSSI and we fail only if it fails.
4624 * In other case we simply override error to indicate success as we
4625 * already remembered if TX power value is actually valid.
4626 */
4627 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4628 if (!cp) {
4629 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4630 status = 0;
4631 }
4632
4633 if (!cp) {
4634 BT_ERR("invalid sent_cmd in response");
4635 goto unlock;
4636 }
4637
4638 handle = __le16_to_cpu(cp->handle);
4639 conn = hci_conn_hash_lookup_handle(hdev, handle);
4640 if (!conn) {
4641 BT_ERR("unknown handle (%d) in response", handle);
4642 goto unlock;
4643 }
4644
4645 match.conn = conn;
4646 match.mgmt_status = mgmt_status(status);
4647
4648 /* Cache refresh is complete, now reply for mgmt request for given
4649 * connection only.
4650 */
4651 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4652 get_conn_info_complete, &match);
4653
4654unlock:
4655 hci_dev_unlock(hdev);
4656}
4657
4658static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4659 u16 len)
4660{
4661 struct mgmt_cp_get_conn_info *cp = data;
4662 struct mgmt_rp_get_conn_info rp;
4663 struct hci_conn *conn;
4664 unsigned long conn_info_age;
4665 int err = 0;
4666
4667 BT_DBG("%s", hdev->name);
4668
4669 memset(&rp, 0, sizeof(rp));
4670 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4671 rp.addr.type = cp->addr.type;
4672
4673 if (!bdaddr_type_is_valid(cp->addr.type))
4674 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4675 MGMT_STATUS_INVALID_PARAMS,
4676 &rp, sizeof(rp));
4677
4678 hci_dev_lock(hdev);
4679
4680 if (!hdev_is_powered(hdev)) {
4681 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4682 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4683 goto unlock;
4684 }
4685
4686 if (cp->addr.type == BDADDR_BREDR)
4687 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4688 &cp->addr.bdaddr);
4689 else
4690 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4691
4692 if (!conn || conn->state != BT_CONNECTED) {
4693 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4694 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4695 goto unlock;
4696 }
4697
4698 /* To avoid client trying to guess when to poll again for information we
4699 * calculate conn info age as random value between min/max set in hdev.
4700 */
4701 conn_info_age = hdev->conn_info_min_age +
4702 prandom_u32_max(hdev->conn_info_max_age -
4703 hdev->conn_info_min_age);
4704
4705 /* Query controller to refresh cached values if they are too old or were
4706 * never read.
4707 */
4708 if (time_after(jiffies, conn->conn_info_timestamp + conn_info_age) ||
4709 !conn->conn_info_timestamp) {
4710 struct hci_request req;
4711 struct hci_cp_read_tx_power req_txp_cp;
4712 struct hci_cp_read_rssi req_rssi_cp;
4713 struct pending_cmd *cmd;
4714
4715 hci_req_init(&req, hdev);
4716 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4717 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4718 &req_rssi_cp);
4719
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004720 /* For LE links TX power does not change thus we don't need to
4721 * query for it once value is known.
4722 */
4723 if (!bdaddr_type_is_le(cp->addr.type) ||
4724 conn->tx_power == HCI_TX_POWER_INVALID) {
4725 req_txp_cp.handle = cpu_to_le16(conn->handle);
4726 req_txp_cp.type = 0x00;
4727 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4728 sizeof(req_txp_cp), &req_txp_cp);
4729 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004730
4731 err = hci_req_run(&req, conn_info_refresh_complete);
4732 if (err < 0)
4733 goto unlock;
4734
4735 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4736 data, len);
4737 if (!cmd) {
4738 err = -ENOMEM;
4739 goto unlock;
4740 }
4741
4742 hci_conn_hold(conn);
4743 cmd->user_data = conn;
4744
4745 conn->conn_info_timestamp = jiffies;
4746 } else {
4747 /* Cache is valid, just reply with values cached in hci_conn */
4748 rp.rssi = conn->rssi;
4749 rp.tx_power = conn->tx_power;
4750 rp.max_tx_power = HCI_TX_POWER_INVALID;
4751
4752 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4753 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4754 }
4755
4756unlock:
4757 hci_dev_unlock(hdev);
4758 return err;
4759}
4760
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004761static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004762 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4763 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004764 bool var_len;
4765 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004766} mgmt_handlers[] = {
4767 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004768 { read_version, false, MGMT_READ_VERSION_SIZE },
4769 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4770 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4771 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4772 { set_powered, false, MGMT_SETTING_SIZE },
4773 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4774 { set_connectable, false, MGMT_SETTING_SIZE },
4775 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4776 { set_pairable, false, MGMT_SETTING_SIZE },
4777 { set_link_security, false, MGMT_SETTING_SIZE },
4778 { set_ssp, false, MGMT_SETTING_SIZE },
4779 { set_hs, false, MGMT_SETTING_SIZE },
4780 { set_le, false, MGMT_SETTING_SIZE },
4781 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4782 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4783 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4784 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4785 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4786 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4787 { disconnect, false, MGMT_DISCONNECT_SIZE },
4788 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4789 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4790 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4791 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4792 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4793 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4794 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4795 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4796 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4797 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4798 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4799 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004800 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004801 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4802 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4803 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4804 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4805 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4806 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004807 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004808 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004809 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004810 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004811 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004812 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004813 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004814 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004815 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004816 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004817};
4818
4819
Johan Hedberg03811012010-12-08 00:21:06 +02004820int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4821{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004822 void *buf;
4823 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004824 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004825 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004826 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004827 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004828 int err;
4829
4830 BT_DBG("got %zu bytes", msglen);
4831
4832 if (msglen < sizeof(*hdr))
4833 return -EINVAL;
4834
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004835 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004836 if (!buf)
4837 return -ENOMEM;
4838
4839 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4840 err = -EFAULT;
4841 goto done;
4842 }
4843
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004844 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004845 opcode = __le16_to_cpu(hdr->opcode);
4846 index = __le16_to_cpu(hdr->index);
4847 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004848
4849 if (len != msglen - sizeof(*hdr)) {
4850 err = -EINVAL;
4851 goto done;
4852 }
4853
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004854 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004855 hdev = hci_dev_get(index);
4856 if (!hdev) {
4857 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004858 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004859 goto done;
4860 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004861
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004862 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4863 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004864 err = cmd_status(sk, index, opcode,
4865 MGMT_STATUS_INVALID_INDEX);
4866 goto done;
4867 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004868 }
4869
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004870 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004871 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004872 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004873 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004874 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004875 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004876 }
4877
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004878 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004879 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004880 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004881 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004882 goto done;
4883 }
4884
Johan Hedbergbe22b542012-03-01 22:24:41 +02004885 handler = &mgmt_handlers[opcode];
4886
4887 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004888 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004889 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004890 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004891 goto done;
4892 }
4893
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004894 if (hdev)
4895 mgmt_init_hdev(sk, hdev);
4896
4897 cp = buf + sizeof(*hdr);
4898
Johan Hedbergbe22b542012-03-01 22:24:41 +02004899 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004900 if (err < 0)
4901 goto done;
4902
Johan Hedberg03811012010-12-08 00:21:06 +02004903 err = msglen;
4904
4905done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004906 if (hdev)
4907 hci_dev_put(hdev);
4908
Johan Hedberg03811012010-12-08 00:21:06 +02004909 kfree(buf);
4910 return err;
4911}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004912
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004913void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004914{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004915 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004916 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004917
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004918 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004919}
4920
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004921void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004922{
Johan Hedberg5f159032012-03-02 03:13:19 +02004923 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004924
Marcel Holtmann1514b892013-10-06 08:25:01 -07004925 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004926 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004927
Johan Hedberg744cf192011-11-08 20:40:14 +02004928 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004929
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004930 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004931}
4932
Andre Guedes6046dc32014-02-26 20:21:51 -03004933/* This function requires the caller holds hdev->lock */
4934static void restart_le_auto_conns(struct hci_dev *hdev)
4935{
4936 struct hci_conn_params *p;
4937
4938 list_for_each_entry(p, &hdev->le_conn_params, list) {
4939 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4940 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4941 }
4942}
4943
Johan Hedberg229ab392013-03-15 17:06:53 -05004944static void powered_complete(struct hci_dev *hdev, u8 status)
4945{
4946 struct cmd_lookup match = { NULL, hdev };
4947
4948 BT_DBG("status 0x%02x", status);
4949
4950 hci_dev_lock(hdev);
4951
Andre Guedes6046dc32014-02-26 20:21:51 -03004952 restart_le_auto_conns(hdev);
4953
Johan Hedberg229ab392013-03-15 17:06:53 -05004954 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4955
4956 new_settings(hdev, match.sk);
4957
4958 hci_dev_unlock(hdev);
4959
4960 if (match.sk)
4961 sock_put(match.sk);
4962}
4963
Johan Hedberg70da6242013-03-15 17:06:51 -05004964static int powered_update_hci(struct hci_dev *hdev)
4965{
Johan Hedberg890ea892013-03-15 17:06:52 -05004966 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004967 u8 link_sec;
4968
Johan Hedberg890ea892013-03-15 17:06:52 -05004969 hci_req_init(&req, hdev);
4970
Johan Hedberg70da6242013-03-15 17:06:51 -05004971 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4972 !lmp_host_ssp_capable(hdev)) {
4973 u8 ssp = 1;
4974
Johan Hedberg890ea892013-03-15 17:06:52 -05004975 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004976 }
4977
Johan Hedbergc73eee92013-04-19 18:35:21 +03004978 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4979 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004980 struct hci_cp_write_le_host_supported cp;
4981
4982 cp.le = 1;
4983 cp.simul = lmp_le_br_capable(hdev);
4984
4985 /* Check first if we already have the right
4986 * host state (host features set)
4987 */
4988 if (cp.le != lmp_host_le_capable(hdev) ||
4989 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05004990 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
4991 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004992 }
4993
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004994 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07004995 /* Make sure the controller has a good default for
4996 * advertising data. This also applies to the case
4997 * where BR/EDR was toggled during the AUTO_OFF phase.
4998 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004999 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005000 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005001 update_scan_rsp_data(&req);
5002 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005003
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005004 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5005 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005006 }
5007
Johan Hedberg70da6242013-03-15 17:06:51 -05005008 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5009 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005010 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5011 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005012
5013 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005014 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5015 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005016 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005017 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005018 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005019 }
5020
Johan Hedberg229ab392013-03-15 17:06:53 -05005021 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005022}
5023
Johan Hedberg744cf192011-11-08 20:40:14 +02005024int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005025{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005026 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005027 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5028 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005029 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005030
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005031 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5032 return 0;
5033
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005034 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005035 if (powered_update_hci(hdev) == 0)
5036 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005037
Johan Hedberg229ab392013-03-15 17:06:53 -05005038 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5039 &match);
5040 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005041 }
5042
Johan Hedberg229ab392013-03-15 17:06:53 -05005043 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5044 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5045
5046 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5047 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5048 zero_cod, sizeof(zero_cod), NULL);
5049
5050new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005051 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005052
5053 if (match.sk)
5054 sock_put(match.sk);
5055
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005056 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005057}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005058
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005059void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005060{
5061 struct pending_cmd *cmd;
5062 u8 status;
5063
5064 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5065 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005066 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005067
5068 if (err == -ERFKILL)
5069 status = MGMT_STATUS_RFKILLED;
5070 else
5071 status = MGMT_STATUS_FAILED;
5072
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005073 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005074
5075 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005076}
5077
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005078void mgmt_discoverable_timeout(struct hci_dev *hdev)
5079{
5080 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005081
5082 hci_dev_lock(hdev);
5083
5084 /* When discoverable timeout triggers, then just make sure
5085 * the limited discoverable flag is cleared. Even in the case
5086 * of a timeout triggered from general discoverable, it is
5087 * safe to unconditionally clear the flag.
5088 */
5089 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005090 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005091
5092 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005093 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5094 u8 scan = SCAN_PAGE;
5095 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5096 sizeof(scan), &scan);
5097 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005098 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005099 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005100 hci_req_run(&req, NULL);
5101
5102 hdev->discov_timeout = 0;
5103
Johan Hedberg9a43e252013-10-20 19:00:07 +03005104 new_settings(hdev, NULL);
5105
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005106 hci_dev_unlock(hdev);
5107}
5108
Marcel Holtmann86a75642013-10-15 06:33:54 -07005109void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005110{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005111 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005112
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005113 /* Nothing needed here if there's a pending command since that
5114 * commands request completion callback takes care of everything
5115 * necessary.
5116 */
5117 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005118 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005119
Johan Hedbergbd107992014-02-24 14:52:19 +02005120 /* Powering off may clear the scan mode - don't let that interfere */
5121 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5122 return;
5123
Johan Hedberg9a43e252013-10-20 19:00:07 +03005124 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005125 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005126 } else {
5127 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005128 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005129 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005130
Johan Hedberg9a43e252013-10-20 19:00:07 +03005131 if (changed) {
5132 struct hci_request req;
5133
5134 /* In case this change in discoverable was triggered by
5135 * a disabling of connectable there could be a need to
5136 * update the advertising flags.
5137 */
5138 hci_req_init(&req, hdev);
5139 update_adv_data(&req);
5140 hci_req_run(&req, NULL);
5141
Marcel Holtmann86a75642013-10-15 06:33:54 -07005142 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005143 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005144}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005145
Marcel Holtmanna3309162013-10-15 06:33:55 -07005146void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005147{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005148 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005149
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005150 /* Nothing needed here if there's a pending command since that
5151 * commands request completion callback takes care of everything
5152 * necessary.
5153 */
5154 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005155 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005156
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005157 /* Powering off may clear the scan mode - don't let that interfere */
5158 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5159 return;
5160
Marcel Holtmanna3309162013-10-15 06:33:55 -07005161 if (connectable)
5162 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5163 else
5164 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005165
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005166 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005167 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005168}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005169
Johan Hedberg778b2352014-02-24 14:52:17 +02005170void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5171{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005172 /* Powering off may stop advertising - don't let that interfere */
5173 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5174 return;
5175
Johan Hedberg778b2352014-02-24 14:52:17 +02005176 if (advertising)
5177 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5178 else
5179 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5180}
5181
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005182void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005183{
Johan Hedbergca69b792011-11-11 18:10:00 +02005184 u8 mgmt_err = mgmt_status(status);
5185
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005186 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005187 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005188 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005189
5190 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005191 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005192 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005193}
5194
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005195void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5196 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005197{
Johan Hedberg86742e12011-11-07 23:13:38 +02005198 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005199
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005200 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005201
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005202 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005203 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005204 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005205 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005206 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005207 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005208
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005209 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005210}
Johan Hedbergf7520542011-01-20 12:34:39 +02005211
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005212void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005213{
5214 struct mgmt_ev_new_long_term_key ev;
5215
5216 memset(&ev, 0, sizeof(ev));
5217
Marcel Holtmann5192d302014-02-19 17:11:58 -08005218 /* Devices using resolvable or non-resolvable random addresses
5219 * without providing an indentity resolving key don't require
5220 * to store long term keys. Their addresses will change the
5221 * next time around.
5222 *
5223 * Only when a remote device provides an identity address
5224 * make sure the long term key is stored. If the remote
5225 * identity is known, the long term keys are internally
5226 * mapped to the identity address. So allow static random
5227 * and public addresses here.
5228 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005229 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5230 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5231 ev.store_hint = 0x00;
5232 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005233 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005234
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005235 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005236 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08005237 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005238 ev.key.enc_size = key->enc_size;
5239 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005240 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005241
5242 if (key->type == HCI_SMP_LTK)
5243 ev.key.master = 1;
5244
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005245 memcpy(ev.key.val, key->val, sizeof(key->val));
5246
Marcel Holtmann083368f2013-10-15 14:26:29 -07005247 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005248}
5249
Johan Hedberg95fbac82014-02-19 15:18:31 +02005250void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5251{
5252 struct mgmt_ev_new_irk ev;
5253
5254 memset(&ev, 0, sizeof(ev));
5255
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005256 /* For identity resolving keys from devices that are already
5257 * using a public address or static random address, do not
5258 * ask for storing this key. The identity resolving key really
5259 * is only mandatory for devices using resovlable random
5260 * addresses.
5261 *
5262 * Storing all identity resolving keys has the downside that
5263 * they will be also loaded on next boot of they system. More
5264 * identity resolving keys, means more time during scanning is
5265 * needed to actually resolve these addresses.
5266 */
5267 if (bacmp(&irk->rpa, BDADDR_ANY))
5268 ev.store_hint = 0x01;
5269 else
5270 ev.store_hint = 0x00;
5271
Johan Hedberg95fbac82014-02-19 15:18:31 +02005272 bacpy(&ev.rpa, &irk->rpa);
5273 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5274 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5275 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5276
5277 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5278}
5279
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005280void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5281 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005282{
5283 struct mgmt_ev_new_csrk ev;
5284
5285 memset(&ev, 0, sizeof(ev));
5286
5287 /* Devices using resolvable or non-resolvable random addresses
5288 * without providing an indentity resolving key don't require
5289 * to store signature resolving keys. Their addresses will change
5290 * the next time around.
5291 *
5292 * Only when a remote device provides an identity address
5293 * make sure the signature resolving key is stored. So allow
5294 * static random and public addresses here.
5295 */
5296 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5297 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5298 ev.store_hint = 0x00;
5299 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005300 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005301
5302 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5303 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5304 ev.key.master = csrk->master;
5305 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5306
5307 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5308}
5309
Marcel Holtmann94933992013-10-15 10:26:39 -07005310static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5311 u8 data_len)
5312{
5313 eir[eir_len++] = sizeof(type) + data_len;
5314 eir[eir_len++] = type;
5315 memcpy(&eir[eir_len], data, data_len);
5316 eir_len += data_len;
5317
5318 return eir_len;
5319}
5320
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005321void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5322 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5323 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005324{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005325 char buf[512];
5326 struct mgmt_ev_device_connected *ev = (void *) buf;
5327 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005328
Johan Hedbergb644ba32012-01-17 21:48:47 +02005329 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005330 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005331
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005332 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005333
Johan Hedbergb644ba32012-01-17 21:48:47 +02005334 if (name_len > 0)
5335 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005336 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005337
5338 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005339 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005340 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005341
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005342 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005343
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005344 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5345 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005346}
5347
Johan Hedberg8962ee72011-01-20 12:40:27 +02005348static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5349{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005350 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005351 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005352 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005353
Johan Hedberg88c3df12012-02-09 14:27:38 +02005354 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5355 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005356
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005357 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005358 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005359
5360 *sk = cmd->sk;
5361 sock_hold(*sk);
5362
Johan Hedberga664b5b2011-02-19 12:06:02 -03005363 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005364}
5365
Johan Hedberg124f6e32012-02-09 13:50:12 +02005366static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005367{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005368 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005369 struct mgmt_cp_unpair_device *cp = cmd->param;
5370 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005371
5372 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005373 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5374 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005375
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005376 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5377
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005378 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005379
5380 mgmt_pending_remove(cmd);
5381}
5382
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005383void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005384 u8 link_type, u8 addr_type, u8 reason,
5385 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005386{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005387 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005388 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005389 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005390
Johan Hedberg8b064a32014-02-24 14:52:22 +02005391 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5392 if (power_off) {
5393 struct mgmt_mode *cp = power_off->param;
5394
5395 /* The connection is still in hci_conn_hash so test for 1
5396 * instead of 0 to know if this is the last one.
5397 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005398 if (!cp->val && hci_conn_count(hdev) == 1) {
5399 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005400 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005401 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005402 }
5403
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005404 if (!mgmt_connected)
5405 return;
5406
Andre Guedes57eb7762013-10-30 19:01:41 -03005407 if (link_type != ACL_LINK && link_type != LE_LINK)
5408 return;
5409
Johan Hedberg744cf192011-11-08 20:40:14 +02005410 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005411
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005412 bacpy(&ev.addr.bdaddr, bdaddr);
5413 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5414 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005415
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005416 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005417
5418 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005419 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005420
Johan Hedberg124f6e32012-02-09 13:50:12 +02005421 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005422 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005423}
5424
Marcel Holtmann78929242013-10-06 23:55:47 -07005425void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5426 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005427{
Andre Guedes3655bba2013-10-30 19:01:40 -03005428 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5429 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005430 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005431 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005432
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005433 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5434 hdev);
5435
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005436 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005437 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005438 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005439
Andre Guedes3655bba2013-10-30 19:01:40 -03005440 cp = cmd->param;
5441
5442 if (bacmp(bdaddr, &cp->addr.bdaddr))
5443 return;
5444
5445 if (cp->addr.type != bdaddr_type)
5446 return;
5447
Johan Hedberg88c3df12012-02-09 14:27:38 +02005448 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005449 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005450
Marcel Holtmann78929242013-10-06 23:55:47 -07005451 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5452 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005453
Johan Hedberga664b5b2011-02-19 12:06:02 -03005454 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005455}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005456
Marcel Holtmann445608d2013-10-06 23:55:48 -07005457void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5458 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005459{
5460 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005461 struct pending_cmd *power_off;
5462
5463 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5464 if (power_off) {
5465 struct mgmt_mode *cp = power_off->param;
5466
5467 /* The connection is still in hci_conn_hash so test for 1
5468 * instead of 0 to know if this is the last one.
5469 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005470 if (!cp->val && hci_conn_count(hdev) == 1) {
5471 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005472 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005473 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005474 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005475
Johan Hedberg4c659c32011-11-07 23:13:39 +02005476 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005477 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005478 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005479
Marcel Holtmann445608d2013-10-06 23:55:48 -07005480 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005481}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005482
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005483void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005484{
5485 struct mgmt_ev_pin_code_request ev;
5486
Johan Hedbergd8457692012-02-17 14:24:57 +02005487 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005488 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005489 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005490
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005491 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005492}
5493
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005494void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5495 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005496{
5497 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005498 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005499
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005500 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005501 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005502 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005503
Johan Hedbergd8457692012-02-17 14:24:57 +02005504 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005505 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005506
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005507 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5508 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005509
Johan Hedberga664b5b2011-02-19 12:06:02 -03005510 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005511}
5512
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005513void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5514 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005515{
5516 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005517 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005518
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005519 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005520 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005521 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005522
Johan Hedbergd8457692012-02-17 14:24:57 +02005523 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005524 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005525
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005526 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5527 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005528
Johan Hedberga664b5b2011-02-19 12:06:02 -03005529 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005530}
Johan Hedberga5c29682011-02-19 12:05:57 -03005531
Johan Hedberg744cf192011-11-08 20:40:14 +02005532int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005533 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005534 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005535{
5536 struct mgmt_ev_user_confirm_request ev;
5537
Johan Hedberg744cf192011-11-08 20:40:14 +02005538 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005539
Johan Hedberg272d90d2012-02-09 15:26:12 +02005540 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005541 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005542 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005543 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005544
Johan Hedberg744cf192011-11-08 20:40:14 +02005545 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005546 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005547}
5548
Johan Hedberg272d90d2012-02-09 15:26:12 +02005549int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005550 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005551{
5552 struct mgmt_ev_user_passkey_request ev;
5553
5554 BT_DBG("%s", hdev->name);
5555
Johan Hedberg272d90d2012-02-09 15:26:12 +02005556 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005557 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005558
5559 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005560 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005561}
5562
Brian Gix0df4c182011-11-16 13:53:13 -08005563static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005564 u8 link_type, u8 addr_type, u8 status,
5565 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005566{
5567 struct pending_cmd *cmd;
5568 struct mgmt_rp_user_confirm_reply rp;
5569 int err;
5570
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005571 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005572 if (!cmd)
5573 return -ENOENT;
5574
Johan Hedberg272d90d2012-02-09 15:26:12 +02005575 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005576 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005577 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005578 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005579
Johan Hedberga664b5b2011-02-19 12:06:02 -03005580 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005581
5582 return err;
5583}
5584
Johan Hedberg744cf192011-11-08 20:40:14 +02005585int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005586 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005587{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005588 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005589 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005590}
5591
Johan Hedberg272d90d2012-02-09 15:26:12 +02005592int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005593 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005594{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005595 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005596 status,
5597 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005598}
Johan Hedberg2a611692011-02-19 12:06:00 -03005599
Brian Gix604086b2011-11-23 08:28:33 -08005600int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005601 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005602{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005603 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005604 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005605}
5606
Johan Hedberg272d90d2012-02-09 15:26:12 +02005607int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005608 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005609{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005610 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005611 status,
5612 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005613}
5614
Johan Hedberg92a25252012-09-06 18:39:26 +03005615int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5616 u8 link_type, u8 addr_type, u32 passkey,
5617 u8 entered)
5618{
5619 struct mgmt_ev_passkey_notify ev;
5620
5621 BT_DBG("%s", hdev->name);
5622
5623 bacpy(&ev.addr.bdaddr, bdaddr);
5624 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5625 ev.passkey = __cpu_to_le32(passkey);
5626 ev.entered = entered;
5627
5628 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5629}
5630
Marcel Holtmanne5460992013-10-15 14:26:23 -07005631void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5632 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005633{
5634 struct mgmt_ev_auth_failed ev;
5635
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005636 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005637 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005638 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005639
Marcel Holtmanne5460992013-10-15 14:26:23 -07005640 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005641}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005642
Marcel Holtmann464996a2013-10-15 14:26:24 -07005643void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005644{
5645 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005646 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005647
5648 if (status) {
5649 u8 mgmt_err = mgmt_status(status);
5650 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005651 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005652 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005653 }
5654
Marcel Holtmann464996a2013-10-15 14:26:24 -07005655 if (test_bit(HCI_AUTH, &hdev->flags))
5656 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5657 &hdev->dev_flags);
5658 else
5659 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5660 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005661
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005662 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005663 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005664
Johan Hedberg47990ea2012-02-22 11:58:37 +02005665 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005666 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005667
5668 if (match.sk)
5669 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005670}
5671
Johan Hedberg890ea892013-03-15 17:06:52 -05005672static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005673{
Johan Hedberg890ea892013-03-15 17:06:52 -05005674 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005675 struct hci_cp_write_eir cp;
5676
Johan Hedberg976eb202012-10-24 21:12:01 +03005677 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005678 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005679
Johan Hedbergc80da272012-02-22 15:38:48 +02005680 memset(hdev->eir, 0, sizeof(hdev->eir));
5681
Johan Hedbergcacaf522012-02-21 00:52:42 +02005682 memset(&cp, 0, sizeof(cp));
5683
Johan Hedberg890ea892013-03-15 17:06:52 -05005684 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005685}
5686
Marcel Holtmann3e248562013-10-15 14:26:25 -07005687void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005688{
5689 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005690 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005691 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005692
5693 if (status) {
5694 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005695
5696 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005697 &hdev->dev_flags)) {
5698 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005699 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005700 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005701
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005702 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5703 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005704 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005705 }
5706
5707 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005708 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005709 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005710 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5711 if (!changed)
5712 changed = test_and_clear_bit(HCI_HS_ENABLED,
5713 &hdev->dev_flags);
5714 else
5715 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005716 }
5717
5718 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5719
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005720 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005721 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005722
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005723 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005724 sock_put(match.sk);
5725
Johan Hedberg890ea892013-03-15 17:06:52 -05005726 hci_req_init(&req, hdev);
5727
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005728 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005729 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005730 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005731 clear_eir(&req);
5732
5733 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005734}
5735
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005736void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5737{
5738 struct cmd_lookup match = { NULL, hdev };
5739 bool changed = false;
5740
5741 if (status) {
5742 u8 mgmt_err = mgmt_status(status);
5743
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005744 if (enable) {
5745 if (test_and_clear_bit(HCI_SC_ENABLED,
5746 &hdev->dev_flags))
5747 new_settings(hdev, NULL);
5748 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5749 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005750
5751 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5752 cmd_status_rsp, &mgmt_err);
5753 return;
5754 }
5755
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005756 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005757 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005758 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005759 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005760 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5761 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005762
5763 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5764 settings_rsp, &match);
5765
5766 if (changed)
5767 new_settings(hdev, match.sk);
5768
5769 if (match.sk)
5770 sock_put(match.sk);
5771}
5772
Johan Hedberg92da6092013-03-15 17:06:55 -05005773static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005774{
5775 struct cmd_lookup *match = data;
5776
Johan Hedberg90e70452012-02-23 23:09:40 +02005777 if (match->sk == NULL) {
5778 match->sk = cmd->sk;
5779 sock_hold(match->sk);
5780 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005781}
5782
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005783void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5784 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005785{
Johan Hedberg90e70452012-02-23 23:09:40 +02005786 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005787
Johan Hedberg92da6092013-03-15 17:06:55 -05005788 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5789 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5790 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005791
5792 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005793 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5794 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005795
5796 if (match.sk)
5797 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005798}
5799
Marcel Holtmann7667da32013-10-15 14:26:27 -07005800void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005801{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005802 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005803 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005804
Johan Hedberg13928972013-03-15 17:07:00 -05005805 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005806 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005807
5808 memset(&ev, 0, sizeof(ev));
5809 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005810 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005811
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005812 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005813 if (!cmd) {
5814 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005815
Johan Hedberg13928972013-03-15 17:07:00 -05005816 /* If this is a HCI command related to powering on the
5817 * HCI dev don't send any mgmt signals.
5818 */
5819 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005820 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005821 }
5822
Marcel Holtmann7667da32013-10-15 14:26:27 -07005823 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5824 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005825}
Szymon Jancc35938b2011-03-22 13:12:21 +01005826
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005827void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5828 u8 *randomizer192, u8 *hash256,
5829 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005830{
5831 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005832
Johan Hedberg744cf192011-11-08 20:40:14 +02005833 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005834
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005835 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005836 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005837 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005838
5839 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005840 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5841 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005842 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005843 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5844 hash256 && randomizer256) {
5845 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005846
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005847 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5848 memcpy(rp.randomizer192, randomizer192,
5849 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005850
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005851 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5852 memcpy(rp.randomizer256, randomizer256,
5853 sizeof(rp.randomizer256));
5854
5855 cmd_complete(cmd->sk, hdev->id,
5856 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5857 &rp, sizeof(rp));
5858 } else {
5859 struct mgmt_rp_read_local_oob_data rp;
5860
5861 memcpy(rp.hash, hash192, sizeof(rp.hash));
5862 memcpy(rp.randomizer, randomizer192,
5863 sizeof(rp.randomizer));
5864
5865 cmd_complete(cmd->sk, hdev->id,
5866 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5867 &rp, sizeof(rp));
5868 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005869 }
5870
5871 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005872}
Johan Hedberge17acd42011-03-30 23:57:16 +03005873
Marcel Holtmann901801b2013-10-06 23:55:51 -07005874void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005875 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5876 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005877 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005878{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005879 char buf[512];
5880 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005881 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005882 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005883
Andre Guedes12602d02013-04-30 15:29:40 -03005884 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005885 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005886
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005887 /* Make sure that the buffer is big enough. The 5 extra bytes
5888 * are for the potential CoD field.
5889 */
5890 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005891 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005892
Johan Hedberg1dc06092012-01-15 21:01:23 +02005893 memset(buf, 0, sizeof(buf));
5894
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005895 irk = hci_get_irk(hdev, bdaddr, addr_type);
5896 if (irk) {
5897 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5898 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5899 } else {
5900 bacpy(&ev->addr.bdaddr, bdaddr);
5901 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5902 }
5903
Johan Hedberge319d2e2012-01-15 19:51:59 +02005904 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005905 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005906 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005907 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005908 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005909
Johan Hedberg1dc06092012-01-15 21:01:23 +02005910 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005911 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005912
Johan Hedberg1dc06092012-01-15 21:01:23 +02005913 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5914 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005915 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005916
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005917 if (scan_rsp_len > 0)
5918 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5919
5920 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5921 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005922
Marcel Holtmann901801b2013-10-06 23:55:51 -07005923 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005924}
Johan Hedberga88a9652011-03-30 13:18:12 +03005925
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005926void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5927 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005928{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005929 struct mgmt_ev_device_found *ev;
5930 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5931 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005932
Johan Hedbergb644ba32012-01-17 21:48:47 +02005933 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005934
Johan Hedbergb644ba32012-01-17 21:48:47 +02005935 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005936
Johan Hedbergb644ba32012-01-17 21:48:47 +02005937 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005938 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005939 ev->rssi = rssi;
5940
5941 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005942 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005943
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005944 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005945
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005946 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005947}
Johan Hedberg314b2382011-04-27 10:29:57 -04005948
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005949void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005950{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005951 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005952 struct pending_cmd *cmd;
5953
Andre Guedes343fb142011-11-22 17:14:19 -03005954 BT_DBG("%s discovering %u", hdev->name, discovering);
5955
Johan Hedberg164a6e72011-11-01 17:06:44 +02005956 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005957 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005958 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005959 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005960
5961 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005962 u8 type = hdev->discovery.type;
5963
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005964 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5965 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005966 mgmt_pending_remove(cmd);
5967 }
5968
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005969 memset(&ev, 0, sizeof(ev));
5970 ev.type = hdev->discovery.type;
5971 ev.discovering = discovering;
5972
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005973 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005974}
Antti Julku5e762442011-08-25 16:48:02 +03005975
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005976int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005977{
5978 struct pending_cmd *cmd;
5979 struct mgmt_ev_device_blocked ev;
5980
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005981 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005982
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005983 bacpy(&ev.addr.bdaddr, bdaddr);
5984 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005985
Johan Hedberg744cf192011-11-08 20:40:14 +02005986 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005987 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03005988}
5989
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005990int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005991{
5992 struct pending_cmd *cmd;
5993 struct mgmt_ev_device_unblocked ev;
5994
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005995 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005996
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005997 bacpy(&ev.addr.bdaddr, bdaddr);
5998 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005999
Johan Hedberg744cf192011-11-08 20:40:14 +02006000 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006001 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006002}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006003
6004static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6005{
6006 BT_DBG("%s status %u", hdev->name, status);
6007
6008 /* Clear the advertising mgmt setting if we failed to re-enable it */
6009 if (status) {
6010 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006011 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006012 }
6013}
6014
6015void mgmt_reenable_advertising(struct hci_dev *hdev)
6016{
6017 struct hci_request req;
6018
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006019 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006020 return;
6021
6022 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6023 return;
6024
6025 hci_req_init(&req, hdev);
6026 enable_advertising(&req);
6027
6028 /* If this fails we have no option but to let user space know
6029 * that we've disabled advertising.
6030 */
6031 if (hci_req_run(&req, adv_enable_complete) < 0) {
6032 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006033 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006034 }
6035}