blob: 370cd42f488be7f71ba610123a83066a36cc56e1 [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
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004586 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004587 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004588 rp.max_tx_power = conn->max_tx_power;
4589 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004590 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004591 rp.max_tx_power = HCI_TX_POWER_INVALID;
4592 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004593 }
4594
4595 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4596 match->mgmt_status, &rp, sizeof(rp));
4597
4598 hci_conn_drop(conn);
4599
4600 mgmt_pending_remove(cmd);
4601}
4602
4603static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4604{
4605 struct hci_cp_read_rssi *cp;
4606 struct hci_conn *conn;
4607 struct cmd_conn_lookup match;
4608 u16 handle;
4609
4610 BT_DBG("status 0x%02x", status);
4611
4612 hci_dev_lock(hdev);
4613
4614 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004615 * otherwise we assume it's not valid. At the moment we assume that
4616 * either both or none of current and max values are valid to keep code
4617 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004618 */
4619 match.valid_tx_power = !status;
4620
4621 /* Commands sent in request are either Read RSSI or Read Transmit Power
4622 * Level so we check which one was last sent to retrieve connection
4623 * handle. Both commands have handle as first parameter so it's safe to
4624 * cast data on the same command struct.
4625 *
4626 * First command sent is always Read RSSI and we fail only if it fails.
4627 * In other case we simply override error to indicate success as we
4628 * already remembered if TX power value is actually valid.
4629 */
4630 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4631 if (!cp) {
4632 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4633 status = 0;
4634 }
4635
4636 if (!cp) {
4637 BT_ERR("invalid sent_cmd in response");
4638 goto unlock;
4639 }
4640
4641 handle = __le16_to_cpu(cp->handle);
4642 conn = hci_conn_hash_lookup_handle(hdev, handle);
4643 if (!conn) {
4644 BT_ERR("unknown handle (%d) in response", handle);
4645 goto unlock;
4646 }
4647
4648 match.conn = conn;
4649 match.mgmt_status = mgmt_status(status);
4650
4651 /* Cache refresh is complete, now reply for mgmt request for given
4652 * connection only.
4653 */
4654 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4655 get_conn_info_complete, &match);
4656
4657unlock:
4658 hci_dev_unlock(hdev);
4659}
4660
4661static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4662 u16 len)
4663{
4664 struct mgmt_cp_get_conn_info *cp = data;
4665 struct mgmt_rp_get_conn_info rp;
4666 struct hci_conn *conn;
4667 unsigned long conn_info_age;
4668 int err = 0;
4669
4670 BT_DBG("%s", hdev->name);
4671
4672 memset(&rp, 0, sizeof(rp));
4673 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4674 rp.addr.type = cp->addr.type;
4675
4676 if (!bdaddr_type_is_valid(cp->addr.type))
4677 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4678 MGMT_STATUS_INVALID_PARAMS,
4679 &rp, sizeof(rp));
4680
4681 hci_dev_lock(hdev);
4682
4683 if (!hdev_is_powered(hdev)) {
4684 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4685 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4686 goto unlock;
4687 }
4688
4689 if (cp->addr.type == BDADDR_BREDR)
4690 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4691 &cp->addr.bdaddr);
4692 else
4693 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4694
4695 if (!conn || conn->state != BT_CONNECTED) {
4696 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4697 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4698 goto unlock;
4699 }
4700
4701 /* To avoid client trying to guess when to poll again for information we
4702 * calculate conn info age as random value between min/max set in hdev.
4703 */
4704 conn_info_age = hdev->conn_info_min_age +
4705 prandom_u32_max(hdev->conn_info_max_age -
4706 hdev->conn_info_min_age);
4707
4708 /* Query controller to refresh cached values if they are too old or were
4709 * never read.
4710 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004711 if (time_after(jiffies, conn->conn_info_timestamp +
4712 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004713 !conn->conn_info_timestamp) {
4714 struct hci_request req;
4715 struct hci_cp_read_tx_power req_txp_cp;
4716 struct hci_cp_read_rssi req_rssi_cp;
4717 struct pending_cmd *cmd;
4718
4719 hci_req_init(&req, hdev);
4720 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4721 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4722 &req_rssi_cp);
4723
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004724 /* For LE links TX power does not change thus we don't need to
4725 * query for it once value is known.
4726 */
4727 if (!bdaddr_type_is_le(cp->addr.type) ||
4728 conn->tx_power == HCI_TX_POWER_INVALID) {
4729 req_txp_cp.handle = cpu_to_le16(conn->handle);
4730 req_txp_cp.type = 0x00;
4731 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4732 sizeof(req_txp_cp), &req_txp_cp);
4733 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004734
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004735 /* Max TX power needs to be read only once per connection */
4736 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4737 req_txp_cp.handle = cpu_to_le16(conn->handle);
4738 req_txp_cp.type = 0x01;
4739 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4740 sizeof(req_txp_cp), &req_txp_cp);
4741 }
4742
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004743 err = hci_req_run(&req, conn_info_refresh_complete);
4744 if (err < 0)
4745 goto unlock;
4746
4747 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4748 data, len);
4749 if (!cmd) {
4750 err = -ENOMEM;
4751 goto unlock;
4752 }
4753
4754 hci_conn_hold(conn);
4755 cmd->user_data = conn;
4756
4757 conn->conn_info_timestamp = jiffies;
4758 } else {
4759 /* Cache is valid, just reply with values cached in hci_conn */
4760 rp.rssi = conn->rssi;
4761 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004762 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004763
4764 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4765 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4766 }
4767
4768unlock:
4769 hci_dev_unlock(hdev);
4770 return err;
4771}
4772
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004773static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004774 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4775 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004776 bool var_len;
4777 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004778} mgmt_handlers[] = {
4779 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004780 { read_version, false, MGMT_READ_VERSION_SIZE },
4781 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4782 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4783 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4784 { set_powered, false, MGMT_SETTING_SIZE },
4785 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4786 { set_connectable, false, MGMT_SETTING_SIZE },
4787 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4788 { set_pairable, false, MGMT_SETTING_SIZE },
4789 { set_link_security, false, MGMT_SETTING_SIZE },
4790 { set_ssp, false, MGMT_SETTING_SIZE },
4791 { set_hs, false, MGMT_SETTING_SIZE },
4792 { set_le, false, MGMT_SETTING_SIZE },
4793 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4794 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4795 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4796 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4797 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4798 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4799 { disconnect, false, MGMT_DISCONNECT_SIZE },
4800 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4801 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4802 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4803 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4804 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4805 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4806 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4807 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4808 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4809 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4810 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4811 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004812 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004813 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4814 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4815 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4816 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4817 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4818 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004819 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004820 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004821 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004822 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004823 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004824 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004825 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004826 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004827 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004828 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004829};
4830
4831
Johan Hedberg03811012010-12-08 00:21:06 +02004832int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4833{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004834 void *buf;
4835 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004836 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004837 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004838 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004839 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004840 int err;
4841
4842 BT_DBG("got %zu bytes", msglen);
4843
4844 if (msglen < sizeof(*hdr))
4845 return -EINVAL;
4846
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004847 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004848 if (!buf)
4849 return -ENOMEM;
4850
4851 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4852 err = -EFAULT;
4853 goto done;
4854 }
4855
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004856 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004857 opcode = __le16_to_cpu(hdr->opcode);
4858 index = __le16_to_cpu(hdr->index);
4859 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004860
4861 if (len != msglen - sizeof(*hdr)) {
4862 err = -EINVAL;
4863 goto done;
4864 }
4865
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004866 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004867 hdev = hci_dev_get(index);
4868 if (!hdev) {
4869 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004870 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004871 goto done;
4872 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004873
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004874 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4875 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004876 err = cmd_status(sk, index, opcode,
4877 MGMT_STATUS_INVALID_INDEX);
4878 goto done;
4879 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004880 }
4881
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004882 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004883 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004884 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004885 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004886 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004887 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004888 }
4889
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004890 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004891 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004892 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004893 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004894 goto done;
4895 }
4896
Johan Hedbergbe22b542012-03-01 22:24:41 +02004897 handler = &mgmt_handlers[opcode];
4898
4899 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004900 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004901 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004902 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004903 goto done;
4904 }
4905
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004906 if (hdev)
4907 mgmt_init_hdev(sk, hdev);
4908
4909 cp = buf + sizeof(*hdr);
4910
Johan Hedbergbe22b542012-03-01 22:24:41 +02004911 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004912 if (err < 0)
4913 goto done;
4914
Johan Hedberg03811012010-12-08 00:21:06 +02004915 err = msglen;
4916
4917done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004918 if (hdev)
4919 hci_dev_put(hdev);
4920
Johan Hedberg03811012010-12-08 00:21:06 +02004921 kfree(buf);
4922 return err;
4923}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004924
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004925void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004926{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004927 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004928 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004929
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004930 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004931}
4932
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004933void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004934{
Johan Hedberg5f159032012-03-02 03:13:19 +02004935 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004936
Marcel Holtmann1514b892013-10-06 08:25:01 -07004937 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004938 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004939
Johan Hedberg744cf192011-11-08 20:40:14 +02004940 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004941
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004942 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004943}
4944
Andre Guedes6046dc32014-02-26 20:21:51 -03004945/* This function requires the caller holds hdev->lock */
4946static void restart_le_auto_conns(struct hci_dev *hdev)
4947{
4948 struct hci_conn_params *p;
4949
4950 list_for_each_entry(p, &hdev->le_conn_params, list) {
4951 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4952 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4953 }
4954}
4955
Johan Hedberg229ab392013-03-15 17:06:53 -05004956static void powered_complete(struct hci_dev *hdev, u8 status)
4957{
4958 struct cmd_lookup match = { NULL, hdev };
4959
4960 BT_DBG("status 0x%02x", status);
4961
4962 hci_dev_lock(hdev);
4963
Andre Guedes6046dc32014-02-26 20:21:51 -03004964 restart_le_auto_conns(hdev);
4965
Johan Hedberg229ab392013-03-15 17:06:53 -05004966 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
4967
4968 new_settings(hdev, match.sk);
4969
4970 hci_dev_unlock(hdev);
4971
4972 if (match.sk)
4973 sock_put(match.sk);
4974}
4975
Johan Hedberg70da6242013-03-15 17:06:51 -05004976static int powered_update_hci(struct hci_dev *hdev)
4977{
Johan Hedberg890ea892013-03-15 17:06:52 -05004978 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05004979 u8 link_sec;
4980
Johan Hedberg890ea892013-03-15 17:06:52 -05004981 hci_req_init(&req, hdev);
4982
Johan Hedberg70da6242013-03-15 17:06:51 -05004983 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
4984 !lmp_host_ssp_capable(hdev)) {
4985 u8 ssp = 1;
4986
Johan Hedberg890ea892013-03-15 17:06:52 -05004987 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05004988 }
4989
Johan Hedbergc73eee92013-04-19 18:35:21 +03004990 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4991 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05004992 struct hci_cp_write_le_host_supported cp;
4993
4994 cp.le = 1;
4995 cp.simul = lmp_le_br_capable(hdev);
4996
4997 /* Check first if we already have the right
4998 * host state (host features set)
4999 */
5000 if (cp.le != lmp_host_le_capable(hdev) ||
5001 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005002 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5003 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005004 }
5005
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005006 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005007 /* Make sure the controller has a good default for
5008 * advertising data. This also applies to the case
5009 * where BR/EDR was toggled during the AUTO_OFF phase.
5010 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005011 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005012 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005013 update_scan_rsp_data(&req);
5014 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005015
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005016 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5017 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005018 }
5019
Johan Hedberg70da6242013-03-15 17:06:51 -05005020 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5021 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005022 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5023 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005024
5025 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005026 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5027 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005028 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005029 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005030 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005031 }
5032
Johan Hedberg229ab392013-03-15 17:06:53 -05005033 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005034}
5035
Johan Hedberg744cf192011-11-08 20:40:14 +02005036int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005037{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005038 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005039 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5040 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005041 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005042
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005043 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5044 return 0;
5045
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005046 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005047 if (powered_update_hci(hdev) == 0)
5048 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005049
Johan Hedberg229ab392013-03-15 17:06:53 -05005050 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5051 &match);
5052 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005053 }
5054
Johan Hedberg229ab392013-03-15 17:06:53 -05005055 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5056 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5057
5058 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5059 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5060 zero_cod, sizeof(zero_cod), NULL);
5061
5062new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005063 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005064
5065 if (match.sk)
5066 sock_put(match.sk);
5067
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005068 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005069}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005070
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005071void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005072{
5073 struct pending_cmd *cmd;
5074 u8 status;
5075
5076 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5077 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005078 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005079
5080 if (err == -ERFKILL)
5081 status = MGMT_STATUS_RFKILLED;
5082 else
5083 status = MGMT_STATUS_FAILED;
5084
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005085 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005086
5087 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005088}
5089
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005090void mgmt_discoverable_timeout(struct hci_dev *hdev)
5091{
5092 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005093
5094 hci_dev_lock(hdev);
5095
5096 /* When discoverable timeout triggers, then just make sure
5097 * the limited discoverable flag is cleared. Even in the case
5098 * of a timeout triggered from general discoverable, it is
5099 * safe to unconditionally clear the flag.
5100 */
5101 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005102 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005103
5104 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005105 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5106 u8 scan = SCAN_PAGE;
5107 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5108 sizeof(scan), &scan);
5109 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005110 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005111 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005112 hci_req_run(&req, NULL);
5113
5114 hdev->discov_timeout = 0;
5115
Johan Hedberg9a43e252013-10-20 19:00:07 +03005116 new_settings(hdev, NULL);
5117
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005118 hci_dev_unlock(hdev);
5119}
5120
Marcel Holtmann86a75642013-10-15 06:33:54 -07005121void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005122{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005123 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005124
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005125 /* Nothing needed here if there's a pending command since that
5126 * commands request completion callback takes care of everything
5127 * necessary.
5128 */
5129 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005130 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005131
Johan Hedbergbd107992014-02-24 14:52:19 +02005132 /* Powering off may clear the scan mode - don't let that interfere */
5133 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5134 return;
5135
Johan Hedberg9a43e252013-10-20 19:00:07 +03005136 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005137 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005138 } else {
5139 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005140 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005141 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005142
Johan Hedberg9a43e252013-10-20 19:00:07 +03005143 if (changed) {
5144 struct hci_request req;
5145
5146 /* In case this change in discoverable was triggered by
5147 * a disabling of connectable there could be a need to
5148 * update the advertising flags.
5149 */
5150 hci_req_init(&req, hdev);
5151 update_adv_data(&req);
5152 hci_req_run(&req, NULL);
5153
Marcel Holtmann86a75642013-10-15 06:33:54 -07005154 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005155 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005156}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005157
Marcel Holtmanna3309162013-10-15 06:33:55 -07005158void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005159{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005160 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005161
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005162 /* Nothing needed here if there's a pending command since that
5163 * commands request completion callback takes care of everything
5164 * necessary.
5165 */
5166 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005167 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005168
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005169 /* Powering off may clear the scan mode - don't let that interfere */
5170 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5171 return;
5172
Marcel Holtmanna3309162013-10-15 06:33:55 -07005173 if (connectable)
5174 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5175 else
5176 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005177
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005178 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005179 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005180}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005181
Johan Hedberg778b2352014-02-24 14:52:17 +02005182void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5183{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005184 /* Powering off may stop advertising - don't let that interfere */
5185 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5186 return;
5187
Johan Hedberg778b2352014-02-24 14:52:17 +02005188 if (advertising)
5189 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5190 else
5191 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5192}
5193
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005194void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005195{
Johan Hedbergca69b792011-11-11 18:10:00 +02005196 u8 mgmt_err = mgmt_status(status);
5197
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005198 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005199 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005200 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005201
5202 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005203 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005204 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005205}
5206
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005207void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5208 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005209{
Johan Hedberg86742e12011-11-07 23:13:38 +02005210 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005211
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005212 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005213
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005214 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005215 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005216 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005217 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005218 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005219 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005220
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005221 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005222}
Johan Hedbergf7520542011-01-20 12:34:39 +02005223
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005224void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005225{
5226 struct mgmt_ev_new_long_term_key ev;
5227
5228 memset(&ev, 0, sizeof(ev));
5229
Marcel Holtmann5192d302014-02-19 17:11:58 -08005230 /* Devices using resolvable or non-resolvable random addresses
5231 * without providing an indentity resolving key don't require
5232 * to store long term keys. Their addresses will change the
5233 * next time around.
5234 *
5235 * Only when a remote device provides an identity address
5236 * make sure the long term key is stored. If the remote
5237 * identity is known, the long term keys are internally
5238 * mapped to the identity address. So allow static random
5239 * and public addresses here.
5240 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005241 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5242 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5243 ev.store_hint = 0x00;
5244 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005245 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005246
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005247 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005248 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Marcel Holtmannd40f3ee2014-01-31 18:42:17 -08005249 ev.key.type = key->authenticated;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005250 ev.key.enc_size = key->enc_size;
5251 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005252 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005253
5254 if (key->type == HCI_SMP_LTK)
5255 ev.key.master = 1;
5256
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005257 memcpy(ev.key.val, key->val, sizeof(key->val));
5258
Marcel Holtmann083368f2013-10-15 14:26:29 -07005259 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005260}
5261
Johan Hedberg95fbac82014-02-19 15:18:31 +02005262void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5263{
5264 struct mgmt_ev_new_irk ev;
5265
5266 memset(&ev, 0, sizeof(ev));
5267
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005268 /* For identity resolving keys from devices that are already
5269 * using a public address or static random address, do not
5270 * ask for storing this key. The identity resolving key really
5271 * is only mandatory for devices using resovlable random
5272 * addresses.
5273 *
5274 * Storing all identity resolving keys has the downside that
5275 * they will be also loaded on next boot of they system. More
5276 * identity resolving keys, means more time during scanning is
5277 * needed to actually resolve these addresses.
5278 */
5279 if (bacmp(&irk->rpa, BDADDR_ANY))
5280 ev.store_hint = 0x01;
5281 else
5282 ev.store_hint = 0x00;
5283
Johan Hedberg95fbac82014-02-19 15:18:31 +02005284 bacpy(&ev.rpa, &irk->rpa);
5285 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5286 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5287 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5288
5289 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5290}
5291
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005292void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5293 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005294{
5295 struct mgmt_ev_new_csrk ev;
5296
5297 memset(&ev, 0, sizeof(ev));
5298
5299 /* Devices using resolvable or non-resolvable random addresses
5300 * without providing an indentity resolving key don't require
5301 * to store signature resolving keys. Their addresses will change
5302 * the next time around.
5303 *
5304 * Only when a remote device provides an identity address
5305 * make sure the signature resolving key is stored. So allow
5306 * static random and public addresses here.
5307 */
5308 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5309 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5310 ev.store_hint = 0x00;
5311 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005312 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005313
5314 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5315 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5316 ev.key.master = csrk->master;
5317 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5318
5319 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5320}
5321
Marcel Holtmann94933992013-10-15 10:26:39 -07005322static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5323 u8 data_len)
5324{
5325 eir[eir_len++] = sizeof(type) + data_len;
5326 eir[eir_len++] = type;
5327 memcpy(&eir[eir_len], data, data_len);
5328 eir_len += data_len;
5329
5330 return eir_len;
5331}
5332
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005333void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5334 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5335 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005336{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005337 char buf[512];
5338 struct mgmt_ev_device_connected *ev = (void *) buf;
5339 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005340
Johan Hedbergb644ba32012-01-17 21:48:47 +02005341 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005342 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005343
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005344 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005345
Johan Hedbergb644ba32012-01-17 21:48:47 +02005346 if (name_len > 0)
5347 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005348 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005349
5350 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005351 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005352 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005353
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005354 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005355
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005356 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5357 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005358}
5359
Johan Hedberg8962ee72011-01-20 12:40:27 +02005360static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5361{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005362 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005363 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005364 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005365
Johan Hedberg88c3df12012-02-09 14:27:38 +02005366 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5367 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005368
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005369 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005370 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005371
5372 *sk = cmd->sk;
5373 sock_hold(*sk);
5374
Johan Hedberga664b5b2011-02-19 12:06:02 -03005375 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005376}
5377
Johan Hedberg124f6e32012-02-09 13:50:12 +02005378static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005379{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005380 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005381 struct mgmt_cp_unpair_device *cp = cmd->param;
5382 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005383
5384 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005385 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5386 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005387
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005388 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5389
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005390 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005391
5392 mgmt_pending_remove(cmd);
5393}
5394
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005395void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005396 u8 link_type, u8 addr_type, u8 reason,
5397 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005398{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005399 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005400 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005401 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005402
Johan Hedberg8b064a32014-02-24 14:52:22 +02005403 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5404 if (power_off) {
5405 struct mgmt_mode *cp = power_off->param;
5406
5407 /* The connection is still in hci_conn_hash so test for 1
5408 * instead of 0 to know if this is the last one.
5409 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005410 if (!cp->val && hci_conn_count(hdev) == 1) {
5411 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005412 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005413 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005414 }
5415
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005416 if (!mgmt_connected)
5417 return;
5418
Andre Guedes57eb7762013-10-30 19:01:41 -03005419 if (link_type != ACL_LINK && link_type != LE_LINK)
5420 return;
5421
Johan Hedberg744cf192011-11-08 20:40:14 +02005422 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005423
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005424 bacpy(&ev.addr.bdaddr, bdaddr);
5425 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5426 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005427
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005428 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005429
5430 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005431 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005432
Johan Hedberg124f6e32012-02-09 13:50:12 +02005433 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005434 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005435}
5436
Marcel Holtmann78929242013-10-06 23:55:47 -07005437void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5438 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005439{
Andre Guedes3655bba2013-10-30 19:01:40 -03005440 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5441 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005442 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005443 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005444
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005445 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5446 hdev);
5447
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005448 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005449 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005450 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005451
Andre Guedes3655bba2013-10-30 19:01:40 -03005452 cp = cmd->param;
5453
5454 if (bacmp(bdaddr, &cp->addr.bdaddr))
5455 return;
5456
5457 if (cp->addr.type != bdaddr_type)
5458 return;
5459
Johan Hedberg88c3df12012-02-09 14:27:38 +02005460 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005461 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005462
Marcel Holtmann78929242013-10-06 23:55:47 -07005463 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5464 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005465
Johan Hedberga664b5b2011-02-19 12:06:02 -03005466 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005467}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005468
Marcel Holtmann445608d2013-10-06 23:55:48 -07005469void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5470 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005471{
5472 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005473 struct pending_cmd *power_off;
5474
5475 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5476 if (power_off) {
5477 struct mgmt_mode *cp = power_off->param;
5478
5479 /* The connection is still in hci_conn_hash so test for 1
5480 * instead of 0 to know if this is the last one.
5481 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005482 if (!cp->val && hci_conn_count(hdev) == 1) {
5483 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005484 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005485 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005486 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005487
Johan Hedberg4c659c32011-11-07 23:13:39 +02005488 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005489 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005490 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005491
Marcel Holtmann445608d2013-10-06 23:55:48 -07005492 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005493}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005494
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005495void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005496{
5497 struct mgmt_ev_pin_code_request ev;
5498
Johan Hedbergd8457692012-02-17 14:24:57 +02005499 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005500 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005501 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005502
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005503 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005504}
5505
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005506void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5507 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005508{
5509 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005510 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005511
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005512 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005513 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005514 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005515
Johan Hedbergd8457692012-02-17 14:24:57 +02005516 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005517 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005518
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005519 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5520 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005521
Johan Hedberga664b5b2011-02-19 12:06:02 -03005522 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005523}
5524
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005525void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5526 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005527{
5528 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005529 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005530
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005531 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005532 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005533 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005534
Johan Hedbergd8457692012-02-17 14:24:57 +02005535 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005536 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005537
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005538 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5539 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005540
Johan Hedberga664b5b2011-02-19 12:06:02 -03005541 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005542}
Johan Hedberga5c29682011-02-19 12:05:57 -03005543
Johan Hedberg744cf192011-11-08 20:40:14 +02005544int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005545 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005546 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005547{
5548 struct mgmt_ev_user_confirm_request ev;
5549
Johan Hedberg744cf192011-11-08 20:40:14 +02005550 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005551
Johan Hedberg272d90d2012-02-09 15:26:12 +02005552 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005553 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005554 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005555 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005556
Johan Hedberg744cf192011-11-08 20:40:14 +02005557 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005558 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005559}
5560
Johan Hedberg272d90d2012-02-09 15:26:12 +02005561int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005562 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005563{
5564 struct mgmt_ev_user_passkey_request ev;
5565
5566 BT_DBG("%s", hdev->name);
5567
Johan Hedberg272d90d2012-02-09 15:26:12 +02005568 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005569 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005570
5571 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005572 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005573}
5574
Brian Gix0df4c182011-11-16 13:53:13 -08005575static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005576 u8 link_type, u8 addr_type, u8 status,
5577 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005578{
5579 struct pending_cmd *cmd;
5580 struct mgmt_rp_user_confirm_reply rp;
5581 int err;
5582
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005583 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005584 if (!cmd)
5585 return -ENOENT;
5586
Johan Hedberg272d90d2012-02-09 15:26:12 +02005587 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005588 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005589 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005590 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005591
Johan Hedberga664b5b2011-02-19 12:06:02 -03005592 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005593
5594 return err;
5595}
5596
Johan Hedberg744cf192011-11-08 20:40:14 +02005597int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005598 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005599{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005600 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005601 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005602}
5603
Johan Hedberg272d90d2012-02-09 15:26:12 +02005604int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005605 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005606{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005607 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005608 status,
5609 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005610}
Johan Hedberg2a611692011-02-19 12:06:00 -03005611
Brian Gix604086b2011-11-23 08:28:33 -08005612int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005613 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005614{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005615 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005616 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005617}
5618
Johan Hedberg272d90d2012-02-09 15:26:12 +02005619int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005620 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005621{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005622 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005623 status,
5624 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005625}
5626
Johan Hedberg92a25252012-09-06 18:39:26 +03005627int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5628 u8 link_type, u8 addr_type, u32 passkey,
5629 u8 entered)
5630{
5631 struct mgmt_ev_passkey_notify ev;
5632
5633 BT_DBG("%s", hdev->name);
5634
5635 bacpy(&ev.addr.bdaddr, bdaddr);
5636 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5637 ev.passkey = __cpu_to_le32(passkey);
5638 ev.entered = entered;
5639
5640 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5641}
5642
Marcel Holtmanne5460992013-10-15 14:26:23 -07005643void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5644 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005645{
5646 struct mgmt_ev_auth_failed ev;
5647
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005648 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005649 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005650 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005651
Marcel Holtmanne5460992013-10-15 14:26:23 -07005652 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005653}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005654
Marcel Holtmann464996a2013-10-15 14:26:24 -07005655void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005656{
5657 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005658 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005659
5660 if (status) {
5661 u8 mgmt_err = mgmt_status(status);
5662 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005663 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005664 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005665 }
5666
Marcel Holtmann464996a2013-10-15 14:26:24 -07005667 if (test_bit(HCI_AUTH, &hdev->flags))
5668 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5669 &hdev->dev_flags);
5670 else
5671 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5672 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005673
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005674 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005675 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005676
Johan Hedberg47990ea2012-02-22 11:58:37 +02005677 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005678 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005679
5680 if (match.sk)
5681 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005682}
5683
Johan Hedberg890ea892013-03-15 17:06:52 -05005684static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005685{
Johan Hedberg890ea892013-03-15 17:06:52 -05005686 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005687 struct hci_cp_write_eir cp;
5688
Johan Hedberg976eb202012-10-24 21:12:01 +03005689 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005690 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005691
Johan Hedbergc80da272012-02-22 15:38:48 +02005692 memset(hdev->eir, 0, sizeof(hdev->eir));
5693
Johan Hedbergcacaf522012-02-21 00:52:42 +02005694 memset(&cp, 0, sizeof(cp));
5695
Johan Hedberg890ea892013-03-15 17:06:52 -05005696 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005697}
5698
Marcel Holtmann3e248562013-10-15 14:26:25 -07005699void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005700{
5701 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005702 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005703 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005704
5705 if (status) {
5706 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005707
5708 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005709 &hdev->dev_flags)) {
5710 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005711 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005712 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005713
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005714 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5715 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005716 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005717 }
5718
5719 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005720 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005721 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005722 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5723 if (!changed)
5724 changed = test_and_clear_bit(HCI_HS_ENABLED,
5725 &hdev->dev_flags);
5726 else
5727 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005728 }
5729
5730 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5731
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005732 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005733 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005734
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005735 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005736 sock_put(match.sk);
5737
Johan Hedberg890ea892013-03-15 17:06:52 -05005738 hci_req_init(&req, hdev);
5739
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005740 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005741 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005742 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005743 clear_eir(&req);
5744
5745 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005746}
5747
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005748void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5749{
5750 struct cmd_lookup match = { NULL, hdev };
5751 bool changed = false;
5752
5753 if (status) {
5754 u8 mgmt_err = mgmt_status(status);
5755
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005756 if (enable) {
5757 if (test_and_clear_bit(HCI_SC_ENABLED,
5758 &hdev->dev_flags))
5759 new_settings(hdev, NULL);
5760 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 cmd_status_rsp, &mgmt_err);
5765 return;
5766 }
5767
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005768 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005769 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005770 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005771 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005772 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5773 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005774
5775 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5776 settings_rsp, &match);
5777
5778 if (changed)
5779 new_settings(hdev, match.sk);
5780
5781 if (match.sk)
5782 sock_put(match.sk);
5783}
5784
Johan Hedberg92da6092013-03-15 17:06:55 -05005785static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005786{
5787 struct cmd_lookup *match = data;
5788
Johan Hedberg90e70452012-02-23 23:09:40 +02005789 if (match->sk == NULL) {
5790 match->sk = cmd->sk;
5791 sock_hold(match->sk);
5792 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005793}
5794
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005795void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5796 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005797{
Johan Hedberg90e70452012-02-23 23:09:40 +02005798 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005799
Johan Hedberg92da6092013-03-15 17:06:55 -05005800 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5801 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5802 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005803
5804 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005805 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5806 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005807
5808 if (match.sk)
5809 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005810}
5811
Marcel Holtmann7667da32013-10-15 14:26:27 -07005812void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005813{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005814 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005815 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005816
Johan Hedberg13928972013-03-15 17:07:00 -05005817 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005818 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005819
5820 memset(&ev, 0, sizeof(ev));
5821 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005822 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005823
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005824 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005825 if (!cmd) {
5826 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005827
Johan Hedberg13928972013-03-15 17:07:00 -05005828 /* If this is a HCI command related to powering on the
5829 * HCI dev don't send any mgmt signals.
5830 */
5831 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005832 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005833 }
5834
Marcel Holtmann7667da32013-10-15 14:26:27 -07005835 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5836 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005837}
Szymon Jancc35938b2011-03-22 13:12:21 +01005838
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005839void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5840 u8 *randomizer192, u8 *hash256,
5841 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005842{
5843 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005844
Johan Hedberg744cf192011-11-08 20:40:14 +02005845 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005846
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005847 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005848 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005849 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005850
5851 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005852 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5853 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005854 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005855 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5856 hash256 && randomizer256) {
5857 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005858
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005859 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5860 memcpy(rp.randomizer192, randomizer192,
5861 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005862
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005863 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5864 memcpy(rp.randomizer256, randomizer256,
5865 sizeof(rp.randomizer256));
5866
5867 cmd_complete(cmd->sk, hdev->id,
5868 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5869 &rp, sizeof(rp));
5870 } else {
5871 struct mgmt_rp_read_local_oob_data rp;
5872
5873 memcpy(rp.hash, hash192, sizeof(rp.hash));
5874 memcpy(rp.randomizer, randomizer192,
5875 sizeof(rp.randomizer));
5876
5877 cmd_complete(cmd->sk, hdev->id,
5878 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5879 &rp, sizeof(rp));
5880 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005881 }
5882
5883 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005884}
Johan Hedberge17acd42011-03-30 23:57:16 +03005885
Marcel Holtmann901801b2013-10-06 23:55:51 -07005886void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005887 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5888 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005889 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005890{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005891 char buf[512];
5892 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005893 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005894 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005895
Andre Guedes12602d02013-04-30 15:29:40 -03005896 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005897 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005898
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005899 /* Make sure that the buffer is big enough. The 5 extra bytes
5900 * are for the potential CoD field.
5901 */
5902 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005903 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005904
Johan Hedberg1dc06092012-01-15 21:01:23 +02005905 memset(buf, 0, sizeof(buf));
5906
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005907 irk = hci_get_irk(hdev, bdaddr, addr_type);
5908 if (irk) {
5909 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5910 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5911 } else {
5912 bacpy(&ev->addr.bdaddr, bdaddr);
5913 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5914 }
5915
Johan Hedberge319d2e2012-01-15 19:51:59 +02005916 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005917 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005918 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005919 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005920 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005921
Johan Hedberg1dc06092012-01-15 21:01:23 +02005922 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005923 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005924
Johan Hedberg1dc06092012-01-15 21:01:23 +02005925 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5926 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005927 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005928
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005929 if (scan_rsp_len > 0)
5930 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5931
5932 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5933 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005934
Marcel Holtmann901801b2013-10-06 23:55:51 -07005935 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005936}
Johan Hedberga88a9652011-03-30 13:18:12 +03005937
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005938void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5939 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005940{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005941 struct mgmt_ev_device_found *ev;
5942 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5943 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005944
Johan Hedbergb644ba32012-01-17 21:48:47 +02005945 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005946
Johan Hedbergb644ba32012-01-17 21:48:47 +02005947 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005948
Johan Hedbergb644ba32012-01-17 21:48:47 +02005949 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005950 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005951 ev->rssi = rssi;
5952
5953 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005954 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005955
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005956 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005957
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005958 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03005959}
Johan Hedberg314b2382011-04-27 10:29:57 -04005960
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005961void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04005962{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005963 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02005964 struct pending_cmd *cmd;
5965
Andre Guedes343fb142011-11-22 17:14:19 -03005966 BT_DBG("%s discovering %u", hdev->name, discovering);
5967
Johan Hedberg164a6e72011-11-01 17:06:44 +02005968 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005969 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005970 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005971 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02005972
5973 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02005974 u8 type = hdev->discovery.type;
5975
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005976 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
5977 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02005978 mgmt_pending_remove(cmd);
5979 }
5980
Johan Hedbergf963e8e2012-02-20 23:30:44 +02005981 memset(&ev, 0, sizeof(ev));
5982 ev.type = hdev->discovery.type;
5983 ev.discovering = discovering;
5984
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07005985 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04005986}
Antti Julku5e762442011-08-25 16:48:02 +03005987
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005988int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03005989{
5990 struct pending_cmd *cmd;
5991 struct mgmt_ev_device_blocked ev;
5992
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005993 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03005994
Johan Hedberg88c1fe42012-02-09 15:56:11 +02005995 bacpy(&ev.addr.bdaddr, bdaddr);
5996 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03005997
Johan Hedberg744cf192011-11-08 20:40:14 +02005998 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005999 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006000}
6001
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006002int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006003{
6004 struct pending_cmd *cmd;
6005 struct mgmt_ev_device_unblocked ev;
6006
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006007 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006008
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006009 bacpy(&ev.addr.bdaddr, bdaddr);
6010 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006011
Johan Hedberg744cf192011-11-08 20:40:14 +02006012 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006013 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006014}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006015
6016static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6017{
6018 BT_DBG("%s status %u", hdev->name, status);
6019
6020 /* Clear the advertising mgmt setting if we failed to re-enable it */
6021 if (status) {
6022 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006023 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006024 }
6025}
6026
6027void mgmt_reenable_advertising(struct hci_dev *hdev)
6028{
6029 struct hci_request req;
6030
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006031 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006032 return;
6033
6034 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6035 return;
6036
6037 hci_req_init(&req, hdev);
6038 enable_advertising(&req);
6039
6040 /* If this fails we have no option but to let user space know
6041 * that we've disabled advertising.
6042 */
6043 if (hci_req_run(&req, adv_enable_complete) < 0) {
6044 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006045 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006046 }
6047}