blob: 325bb8136d2c9bb3e47b30cbe1a36f982fe3cef1 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020093};
94
95static const u16 mgmt_events[] = {
96 MGMT_EV_CONTROLLER_ERROR,
97 MGMT_EV_INDEX_ADDED,
98 MGMT_EV_INDEX_REMOVED,
99 MGMT_EV_NEW_SETTINGS,
100 MGMT_EV_CLASS_OF_DEV_CHANGED,
101 MGMT_EV_LOCAL_NAME_CHANGED,
102 MGMT_EV_NEW_LINK_KEY,
103 MGMT_EV_NEW_LONG_TERM_KEY,
104 MGMT_EV_DEVICE_CONNECTED,
105 MGMT_EV_DEVICE_DISCONNECTED,
106 MGMT_EV_CONNECT_FAILED,
107 MGMT_EV_PIN_CODE_REQUEST,
108 MGMT_EV_USER_CONFIRM_REQUEST,
109 MGMT_EV_USER_PASSKEY_REQUEST,
110 MGMT_EV_AUTH_FAILED,
111 MGMT_EV_DEVICE_FOUND,
112 MGMT_EV_DISCOVERING,
113 MGMT_EV_DEVICE_BLOCKED,
114 MGMT_EV_DEVICE_UNBLOCKED,
115 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300116 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800117 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700118 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200119 MGMT_EV_DEVICE_ADDED,
120 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300121 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200122 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200123 MGMT_EV_UNCONF_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200124};
125
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800126#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200127
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200128#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
129 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
130
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200131struct pending_cmd {
132 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200133 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200134 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100135 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300137 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138};
139
Johan Hedbergca69b792011-11-11 18:10:00 +0200140/* HCI to MGMT error code conversion table */
141static u8 mgmt_status_table[] = {
142 MGMT_STATUS_SUCCESS,
143 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
144 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
145 MGMT_STATUS_FAILED, /* Hardware Failure */
146 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
147 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200148 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200149 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
150 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
151 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
152 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
153 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
154 MGMT_STATUS_BUSY, /* Command Disallowed */
155 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
156 MGMT_STATUS_REJECTED, /* Rejected Security */
157 MGMT_STATUS_REJECTED, /* Rejected Personal */
158 MGMT_STATUS_TIMEOUT, /* Host Timeout */
159 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
160 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
161 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
162 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
163 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
164 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
165 MGMT_STATUS_BUSY, /* Repeated Attempts */
166 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
167 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
168 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
169 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
170 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
171 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
172 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
173 MGMT_STATUS_FAILED, /* Unspecified Error */
174 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
175 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
176 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
177 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
178 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
179 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
180 MGMT_STATUS_FAILED, /* Unit Link Key Used */
181 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
182 MGMT_STATUS_TIMEOUT, /* Instant Passed */
183 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
184 MGMT_STATUS_FAILED, /* Transaction Collision */
185 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
186 MGMT_STATUS_REJECTED, /* QoS Rejected */
187 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
188 MGMT_STATUS_REJECTED, /* Insufficient Security */
189 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
190 MGMT_STATUS_BUSY, /* Role Switch Pending */
191 MGMT_STATUS_FAILED, /* Slot Violation */
192 MGMT_STATUS_FAILED, /* Role Switch Failed */
193 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
194 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
195 MGMT_STATUS_BUSY, /* Host Busy Pairing */
196 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
197 MGMT_STATUS_BUSY, /* Controller Busy */
198 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
199 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
200 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
201 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
202 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
203};
204
205static u8 mgmt_status(u8 hci_status)
206{
207 if (hci_status < ARRAY_SIZE(mgmt_status_table))
208 return mgmt_status_table[hci_status];
209
210 return MGMT_STATUS_FAILED;
211}
212
Szymon Janc4e51eae2011-02-25 19:05:48 +0100213static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200214{
215 struct sk_buff *skb;
216 struct mgmt_hdr *hdr;
217 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300218 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200219
Szymon Janc34eb5252011-02-28 14:10:08 +0100220 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200221
Andre Guedes790eff42012-06-07 19:05:46 -0300222 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200223 if (!skb)
224 return -ENOMEM;
225
226 hdr = (void *) skb_put(skb, sizeof(*hdr));
227
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700228 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100229 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200230 hdr->len = cpu_to_le16(sizeof(*ev));
231
232 ev = (void *) skb_put(skb, sizeof(*ev));
233 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200234 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200235
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300236 err = sock_queue_rcv_skb(sk, skb);
237 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200238 kfree_skb(skb);
239
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300240 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200241}
242
Johan Hedbergaee9b212012-02-18 15:07:59 +0200243static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300244 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200245{
246 struct sk_buff *skb;
247 struct mgmt_hdr *hdr;
248 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300249 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200250
251 BT_DBG("sock %p", sk);
252
Andre Guedes790eff42012-06-07 19:05:46 -0300253 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200254 if (!skb)
255 return -ENOMEM;
256
257 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200258
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700259 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100260 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200261 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200262
Johan Hedberga38528f2011-01-22 06:46:43 +0200263 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200264 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200265 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100266
267 if (rp)
268 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200272 kfree_skb(skb);
273
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100274 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200275}
276
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300277static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
278 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200279{
280 struct mgmt_rp_read_version rp;
281
282 BT_DBG("sock %p", sk);
283
284 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700285 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200286
Johan Hedbergaee9b212012-02-18 15:07:59 +0200287 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300288 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200289}
290
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300291static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
292 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200293{
294 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200295 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
296 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200297 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200298 size_t rp_size;
299 int i, err;
300
301 BT_DBG("sock %p", sk);
302
303 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
304
305 rp = kmalloc(rp_size, GFP_KERNEL);
306 if (!rp)
307 return -ENOMEM;
308
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700309 rp->num_commands = cpu_to_le16(num_commands);
310 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200311
312 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
313 put_unaligned_le16(mgmt_commands[i], opcode);
314
315 for (i = 0; i < num_events; i++, opcode++)
316 put_unaligned_le16(mgmt_events[i], opcode);
317
Johan Hedbergaee9b212012-02-18 15:07:59 +0200318 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300319 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200320 kfree(rp);
321
322 return err;
323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200327{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200328 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200329 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200330 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200331 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300332 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200333
334 BT_DBG("sock %p", sk);
335
336 read_lock(&hci_dev_list_lock);
337
338 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300339 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200340 if (d->dev_type == HCI_BREDR &&
341 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700342 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200343 }
344
Johan Hedberga38528f2011-01-22 06:46:43 +0200345 rp_len = sizeof(*rp) + (2 * count);
346 rp = kmalloc(rp_len, GFP_ATOMIC);
347 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100348 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200349 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100350 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200351
Johan Hedberg476e44c2012-10-19 20:10:46 +0300352 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200353 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200354 if (test_bit(HCI_SETUP, &d->dev_flags) ||
355 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200356 continue;
357
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200358 /* Devices marked as raw-only are neither configured
359 * nor unconfigured controllers.
360 */
361 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700362 continue;
363
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200364 if (d->dev_type == HCI_BREDR &&
365 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700366 rp->index[count++] = cpu_to_le16(d->id);
367 BT_DBG("Added hci%u", d->id);
368 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200369 }
370
Johan Hedberg476e44c2012-10-19 20:10:46 +0300371 rp->num_controllers = cpu_to_le16(count);
372 rp_len = sizeof(*rp) + (2 * count);
373
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200374 read_unlock(&hci_dev_list_lock);
375
Johan Hedbergaee9b212012-02-18 15:07:59 +0200376 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300377 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 kfree(rp);
380
381 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382}
383
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200384static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
385 void *data, u16 data_len)
386{
387 struct mgmt_rp_read_unconf_index_list *rp;
388 struct hci_dev *d;
389 size_t rp_len;
390 u16 count;
391 int err;
392
393 BT_DBG("sock %p", sk);
394
395 read_lock(&hci_dev_list_lock);
396
397 count = 0;
398 list_for_each_entry(d, &hci_dev_list, list) {
399 if (d->dev_type == HCI_BREDR &&
400 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
401 count++;
402 }
403
404 rp_len = sizeof(*rp) + (2 * count);
405 rp = kmalloc(rp_len, GFP_ATOMIC);
406 if (!rp) {
407 read_unlock(&hci_dev_list_lock);
408 return -ENOMEM;
409 }
410
411 count = 0;
412 list_for_each_entry(d, &hci_dev_list, list) {
413 if (test_bit(HCI_SETUP, &d->dev_flags) ||
414 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
415 continue;
416
417 /* Devices marked as raw-only are neither configured
418 * nor unconfigured controllers.
419 */
420 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
421 continue;
422
423 if (d->dev_type == HCI_BREDR &&
424 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
425 rp->index[count++] = cpu_to_le16(d->id);
426 BT_DBG("Added hci%u", d->id);
427 }
428 }
429
430 rp->num_controllers = cpu_to_le16(count);
431 rp_len = sizeof(*rp) + (2 * count);
432
433 read_unlock(&hci_dev_list_lock);
434
435 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
436 0, rp, rp_len);
437
438 kfree(rp);
439
440 return err;
441}
442
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200443static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200444{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200445 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200446
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200447 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200448 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800449 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200450
Andre Guedesed3fa312012-07-24 15:03:46 -0300451 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300452 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500453 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
454 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300455 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200456 settings |= MGMT_SETTING_BREDR;
457 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700458
459 if (lmp_ssp_capable(hdev)) {
460 settings |= MGMT_SETTING_SSP;
461 settings |= MGMT_SETTING_HS;
462 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800463
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800464 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200465 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800466 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700467 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100468
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300469 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200470 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300471 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200472 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300473 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200474
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200475 return settings;
476}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200477
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200478static u32 get_current_settings(struct hci_dev *hdev)
479{
480 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200481
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200482 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100483 settings |= MGMT_SETTING_POWERED;
484
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200485 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200486 settings |= MGMT_SETTING_CONNECTABLE;
487
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500488 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
489 settings |= MGMT_SETTING_FAST_CONNECTABLE;
490
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200491 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200492 settings |= MGMT_SETTING_DISCOVERABLE;
493
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200494 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200495 settings |= MGMT_SETTING_PAIRABLE;
496
Johan Hedberg56f87902013-10-02 13:43:13 +0300497 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200498 settings |= MGMT_SETTING_BREDR;
499
Johan Hedberg06199cf2012-02-22 16:37:11 +0200500 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200501 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200502
Johan Hedberg47990ea2012-02-22 11:58:37 +0200503 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200504 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200505
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200506 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200507 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200508
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200509 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
510 settings |= MGMT_SETTING_HS;
511
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200512 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300513 settings |= MGMT_SETTING_ADVERTISING;
514
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800515 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
516 settings |= MGMT_SETTING_SECURE_CONN;
517
Johan Hedberg0663b292014-06-24 13:15:50 +0300518 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800519 settings |= MGMT_SETTING_DEBUG_KEYS;
520
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200521 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
522 settings |= MGMT_SETTING_PRIVACY;
523
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200524 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200525}
526
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300527#define PNP_INFO_SVCLASS_ID 0x1200
528
Johan Hedberg213202e2013-01-27 00:31:33 +0200529static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
530{
531 u8 *ptr = data, *uuids_start = NULL;
532 struct bt_uuid *uuid;
533
534 if (len < 4)
535 return ptr;
536
537 list_for_each_entry(uuid, &hdev->uuids, list) {
538 u16 uuid16;
539
540 if (uuid->size != 16)
541 continue;
542
543 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
544 if (uuid16 < 0x1100)
545 continue;
546
547 if (uuid16 == PNP_INFO_SVCLASS_ID)
548 continue;
549
550 if (!uuids_start) {
551 uuids_start = ptr;
552 uuids_start[0] = 1;
553 uuids_start[1] = EIR_UUID16_ALL;
554 ptr += 2;
555 }
556
557 /* Stop if not enough space to put next UUID */
558 if ((ptr - data) + sizeof(u16) > len) {
559 uuids_start[1] = EIR_UUID16_SOME;
560 break;
561 }
562
563 *ptr++ = (uuid16 & 0x00ff);
564 *ptr++ = (uuid16 & 0xff00) >> 8;
565 uuids_start[0] += sizeof(uuid16);
566 }
567
568 return ptr;
569}
570
Johan Hedbergcdf19632013-01-27 00:31:34 +0200571static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
572{
573 u8 *ptr = data, *uuids_start = NULL;
574 struct bt_uuid *uuid;
575
576 if (len < 6)
577 return ptr;
578
579 list_for_each_entry(uuid, &hdev->uuids, list) {
580 if (uuid->size != 32)
581 continue;
582
583 if (!uuids_start) {
584 uuids_start = ptr;
585 uuids_start[0] = 1;
586 uuids_start[1] = EIR_UUID32_ALL;
587 ptr += 2;
588 }
589
590 /* Stop if not enough space to put next UUID */
591 if ((ptr - data) + sizeof(u32) > len) {
592 uuids_start[1] = EIR_UUID32_SOME;
593 break;
594 }
595
596 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
597 ptr += sizeof(u32);
598 uuids_start[0] += sizeof(u32);
599 }
600
601 return ptr;
602}
603
Johan Hedbergc00d5752013-01-27 00:31:35 +0200604static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
605{
606 u8 *ptr = data, *uuids_start = NULL;
607 struct bt_uuid *uuid;
608
609 if (len < 18)
610 return ptr;
611
612 list_for_each_entry(uuid, &hdev->uuids, list) {
613 if (uuid->size != 128)
614 continue;
615
616 if (!uuids_start) {
617 uuids_start = ptr;
618 uuids_start[0] = 1;
619 uuids_start[1] = EIR_UUID128_ALL;
620 ptr += 2;
621 }
622
623 /* Stop if not enough space to put next UUID */
624 if ((ptr - data) + 16 > len) {
625 uuids_start[1] = EIR_UUID128_SOME;
626 break;
627 }
628
629 memcpy(ptr, uuid->uuid, 16);
630 ptr += 16;
631 uuids_start[0] += 16;
632 }
633
634 return ptr;
635}
636
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300637static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
638{
639 struct pending_cmd *cmd;
640
641 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
642 if (cmd->opcode == opcode)
643 return cmd;
644 }
645
646 return NULL;
647}
648
Johan Hedberg95868422014-06-28 17:54:07 +0300649static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
650 struct hci_dev *hdev,
651 const void *data)
652{
653 struct pending_cmd *cmd;
654
655 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
656 if (cmd->user_data != data)
657 continue;
658 if (cmd->opcode == opcode)
659 return cmd;
660 }
661
662 return NULL;
663}
664
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700665static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
666{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700667 u8 ad_len = 0;
668 size_t name_len;
669
670 name_len = strlen(hdev->dev_name);
671 if (name_len > 0) {
672 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
673
674 if (name_len > max_len) {
675 name_len = max_len;
676 ptr[1] = EIR_NAME_SHORT;
677 } else
678 ptr[1] = EIR_NAME_COMPLETE;
679
680 ptr[0] = name_len + 1;
681
682 memcpy(ptr + 2, hdev->dev_name, name_len);
683
684 ad_len += (name_len + 2);
685 ptr += (name_len + 2);
686 }
687
688 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700689}
690
691static void update_scan_rsp_data(struct hci_request *req)
692{
693 struct hci_dev *hdev = req->hdev;
694 struct hci_cp_le_set_scan_rsp_data cp;
695 u8 len;
696
Johan Hedberg7751ef12013-10-19 23:38:15 +0300697 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700698 return;
699
700 memset(&cp, 0, sizeof(cp));
701
702 len = create_scan_rsp_data(hdev, cp.data);
703
Johan Hedbergeb438b52013-10-16 15:31:07 +0300704 if (hdev->scan_rsp_data_len == len &&
705 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700706 return;
707
Johan Hedbergeb438b52013-10-16 15:31:07 +0300708 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
709 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700710
711 cp.length = len;
712
713 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
714}
715
Johan Hedberg9a43e252013-10-20 19:00:07 +0300716static u8 get_adv_discov_flags(struct hci_dev *hdev)
717{
718 struct pending_cmd *cmd;
719
720 /* If there's a pending mgmt command the flags will not yet have
721 * their final values, so check for this first.
722 */
723 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
724 if (cmd) {
725 struct mgmt_mode *cp = cmd->param;
726 if (cp->val == 0x01)
727 return LE_AD_GENERAL;
728 else if (cp->val == 0x02)
729 return LE_AD_LIMITED;
730 } else {
731 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
732 return LE_AD_LIMITED;
733 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
734 return LE_AD_GENERAL;
735 }
736
737 return 0;
738}
739
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700740static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700741{
742 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700743
Johan Hedberg9a43e252013-10-20 19:00:07 +0300744 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700745
Johan Hedberge8340042014-01-30 11:16:50 -0800746 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700747 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700748
749 if (flags) {
750 BT_DBG("adv flags 0x%02x", flags);
751
752 ptr[0] = 2;
753 ptr[1] = EIR_FLAGS;
754 ptr[2] = flags;
755
756 ad_len += 3;
757 ptr += 3;
758 }
759
760 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
761 ptr[0] = 2;
762 ptr[1] = EIR_TX_POWER;
763 ptr[2] = (u8) hdev->adv_tx_power;
764
765 ad_len += 3;
766 ptr += 3;
767 }
768
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700769 return ad_len;
770}
771
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700772static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700773{
774 struct hci_dev *hdev = req->hdev;
775 struct hci_cp_le_set_adv_data cp;
776 u8 len;
777
Johan Hedberg10994ce2013-10-19 23:38:16 +0300778 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700779 return;
780
781 memset(&cp, 0, sizeof(cp));
782
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700783 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700784
785 if (hdev->adv_data_len == len &&
786 memcmp(cp.data, hdev->adv_data, len) == 0)
787 return;
788
789 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
790 hdev->adv_data_len = len;
791
792 cp.length = len;
793
794 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
795}
796
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300797static void create_eir(struct hci_dev *hdev, u8 *data)
798{
799 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300800 size_t name_len;
801
802 name_len = strlen(hdev->dev_name);
803
804 if (name_len > 0) {
805 /* EIR Data type */
806 if (name_len > 48) {
807 name_len = 48;
808 ptr[1] = EIR_NAME_SHORT;
809 } else
810 ptr[1] = EIR_NAME_COMPLETE;
811
812 /* EIR Data length */
813 ptr[0] = name_len + 1;
814
815 memcpy(ptr + 2, hdev->dev_name, name_len);
816
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300817 ptr += (name_len + 2);
818 }
819
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100820 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700821 ptr[0] = 2;
822 ptr[1] = EIR_TX_POWER;
823 ptr[2] = (u8) hdev->inq_tx_power;
824
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700825 ptr += 3;
826 }
827
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700828 if (hdev->devid_source > 0) {
829 ptr[0] = 9;
830 ptr[1] = EIR_DEVICE_ID;
831
832 put_unaligned_le16(hdev->devid_source, ptr + 2);
833 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
834 put_unaligned_le16(hdev->devid_product, ptr + 6);
835 put_unaligned_le16(hdev->devid_version, ptr + 8);
836
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700837 ptr += 10;
838 }
839
Johan Hedberg213202e2013-01-27 00:31:33 +0200840 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200841 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200842 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300843}
844
Johan Hedberg890ea892013-03-15 17:06:52 -0500845static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300846{
Johan Hedberg890ea892013-03-15 17:06:52 -0500847 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300848 struct hci_cp_write_eir cp;
849
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200850 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500851 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200852
Johan Hedberg976eb202012-10-24 21:12:01 +0300853 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500854 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300855
Johan Hedberg84bde9d6c2012-01-25 14:21:06 +0200856 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500857 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300858
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200859 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500860 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300861
862 memset(&cp, 0, sizeof(cp));
863
864 create_eir(hdev, cp.data);
865
866 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500867 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300868
869 memcpy(hdev->eir, cp.data, sizeof(cp.data));
870
Johan Hedberg890ea892013-03-15 17:06:52 -0500871 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300872}
873
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200874static u8 get_service_classes(struct hci_dev *hdev)
875{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300876 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200877 u8 val = 0;
878
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300879 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200880 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200881
882 return val;
883}
884
Johan Hedberg890ea892013-03-15 17:06:52 -0500885static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200886{
Johan Hedberg890ea892013-03-15 17:06:52 -0500887 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200888 u8 cod[3];
889
890 BT_DBG("%s", hdev->name);
891
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200892 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500893 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200894
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300895 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
896 return;
897
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200898 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500899 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200900
901 cod[0] = hdev->minor_class;
902 cod[1] = hdev->major_class;
903 cod[2] = get_service_classes(hdev);
904
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700905 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
906 cod[1] |= 0x20;
907
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200908 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500909 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200910
Johan Hedberg890ea892013-03-15 17:06:52 -0500911 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200912}
913
Johan Hedberga4858cb2014-02-25 19:56:31 +0200914static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200915{
916 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200917
918 /* If there's a pending mgmt command the flag will not yet have
919 * it's final value, so check for this first.
920 */
921 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
922 if (cmd) {
923 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200924 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200925 }
926
Johan Hedberga4858cb2014-02-25 19:56:31 +0200927 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200928}
929
930static void enable_advertising(struct hci_request *req)
931{
932 struct hci_dev *hdev = req->hdev;
933 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200934 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200935 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200936
Johan Hedberg8d972502014-02-28 12:54:14 +0200937 /* Clear the HCI_ADVERTISING bit temporarily so that the
938 * hci_update_random_address knows that it's safe to go ahead
939 * and write a new random address. The flag will be set back on
940 * as soon as the SET_ADV_ENABLE HCI command completes.
941 */
942 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
943
Johan Hedberga4858cb2014-02-25 19:56:31 +0200944 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200945
Johan Hedberga4858cb2014-02-25 19:56:31 +0200946 /* Set require_privacy to true only when non-connectable
947 * advertising is used. In that case it is fine to use a
948 * non-resolvable private address.
949 */
950 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200951 return;
952
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800953 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700954 cp.min_interval = cpu_to_le16(0x0800);
955 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200956 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200957 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200958 cp.channel_map = hdev->le_adv_channel_map;
959
960 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
961
962 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
963}
964
965static void disable_advertising(struct hci_request *req)
966{
967 u8 enable = 0x00;
968
969 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
970}
971
Johan Hedberg7d785252011-12-15 00:47:39 +0200972static void service_cache_off(struct work_struct *work)
973{
974 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300975 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200977
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200978 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200979 return;
980
Johan Hedberg890ea892013-03-15 17:06:52 -0500981 hci_req_init(&req, hdev);
982
Johan Hedberg7d785252011-12-15 00:47:39 +0200983 hci_dev_lock(hdev);
984
Johan Hedberg890ea892013-03-15 17:06:52 -0500985 update_eir(&req);
986 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200987
988 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500989
990 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200991}
992
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200993static void rpa_expired(struct work_struct *work)
994{
995 struct hci_dev *hdev = container_of(work, struct hci_dev,
996 rpa_expired.work);
997 struct hci_request req;
998
999 BT_DBG("");
1000
1001 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1002
1003 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1004 hci_conn_num(hdev, LE_LINK) > 0)
1005 return;
1006
1007 /* The generation of a new RPA and programming it into the
1008 * controller happens in the enable_advertising() function.
1009 */
1010
1011 hci_req_init(&req, hdev);
1012
1013 disable_advertising(&req);
1014 enable_advertising(&req);
1015
1016 hci_req_run(&req, NULL);
1017}
1018
Johan Hedberg6a919082012-02-28 06:17:26 +02001019static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001020{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001021 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001022 return;
1023
Johan Hedberg4f87da82012-03-02 19:55:56 +02001024 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001025 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001026
Johan Hedberg4f87da82012-03-02 19:55:56 +02001027 /* Non-mgmt controlled devices get this bit set
1028 * implicitly so that pairing works for them, however
1029 * for mgmt we require user-space to explicitly enable
1030 * it
1031 */
1032 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001033}
1034
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001035static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001036 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001037{
1038 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001039
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001040 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001041
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001042 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001043
Johan Hedberg03811012010-12-08 00:21:06 +02001044 memset(&rp, 0, sizeof(rp));
1045
Johan Hedberg03811012010-12-08 00:21:06 +02001046 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001047
1048 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001049 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001050
1051 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1052 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1053
1054 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001055
1056 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001057 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001059 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001061 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001062 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001063}
1064
1065static void mgmt_pending_free(struct pending_cmd *cmd)
1066{
1067 sock_put(cmd->sk);
1068 kfree(cmd->param);
1069 kfree(cmd);
1070}
1071
1072static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001073 struct hci_dev *hdev, void *data,
1074 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001075{
1076 struct pending_cmd *cmd;
1077
Johan Hedbergfca20012014-06-28 17:54:05 +03001078 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001079 if (!cmd)
1080 return NULL;
1081
1082 cmd->opcode = opcode;
1083 cmd->index = hdev->id;
1084
Andre Guedes12b94562012-06-07 19:05:45 -03001085 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001086 if (!cmd->param) {
1087 kfree(cmd);
1088 return NULL;
1089 }
1090
1091 if (data)
1092 memcpy(cmd->param, data, len);
1093
1094 cmd->sk = sk;
1095 sock_hold(sk);
1096
1097 list_add(&cmd->list, &hdev->mgmt_pending);
1098
1099 return cmd;
1100}
1101
1102static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001103 void (*cb)(struct pending_cmd *cmd,
1104 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001105 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001106{
Andre Guedesa3d09352013-02-01 11:21:30 -03001107 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001108
Andre Guedesa3d09352013-02-01 11:21:30 -03001109 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001110 if (opcode > 0 && cmd->opcode != opcode)
1111 continue;
1112
1113 cb(cmd, data);
1114 }
1115}
1116
Johan Hedberg03811012010-12-08 00:21:06 +02001117static void mgmt_pending_remove(struct pending_cmd *cmd)
1118{
1119 list_del(&cmd->list);
1120 mgmt_pending_free(cmd);
1121}
1122
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001123static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001124{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001125 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001126
Johan Hedbergaee9b212012-02-18 15:07:59 +02001127 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001128 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001129}
1130
Johan Hedberg8b064a32014-02-24 14:52:22 +02001131static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1132{
1133 BT_DBG("%s status 0x%02x", hdev->name, status);
1134
Johan Hedberga3172b72014-02-28 09:33:44 +02001135 if (hci_conn_count(hdev) == 0) {
1136 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001137 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001138 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001139}
1140
Johan Hedberg21a60d32014-06-10 14:05:58 +03001141static void hci_stop_discovery(struct hci_request *req)
1142{
1143 struct hci_dev *hdev = req->hdev;
1144 struct hci_cp_remote_name_req_cancel cp;
1145 struct inquiry_entry *e;
1146
1147 switch (hdev->discovery.state) {
1148 case DISCOVERY_FINDING:
1149 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1150 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1151 } else {
1152 cancel_delayed_work(&hdev->le_scan_disable);
1153 hci_req_add_le_scan_disable(req);
1154 }
1155
1156 break;
1157
1158 case DISCOVERY_RESOLVING:
1159 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1160 NAME_PENDING);
1161 if (!e)
1162 return;
1163
1164 bacpy(&cp.bdaddr, &e->data.bdaddr);
1165 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1166 &cp);
1167
1168 break;
1169
1170 default:
1171 /* Passive scanning */
1172 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1173 hci_req_add_le_scan_disable(req);
1174 break;
1175 }
1176}
1177
Johan Hedberg8b064a32014-02-24 14:52:22 +02001178static int clean_up_hci_state(struct hci_dev *hdev)
1179{
1180 struct hci_request req;
1181 struct hci_conn *conn;
1182
1183 hci_req_init(&req, hdev);
1184
1185 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1186 test_bit(HCI_PSCAN, &hdev->flags)) {
1187 u8 scan = 0x00;
1188 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1189 }
1190
1191 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1192 disable_advertising(&req);
1193
Johan Hedbergf8680f12014-06-10 14:05:59 +03001194 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001195
1196 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1197 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001198 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001199
Johan Hedbergc9910d02014-02-27 14:35:12 +02001200 switch (conn->state) {
1201 case BT_CONNECTED:
1202 case BT_CONFIG:
1203 dc.handle = cpu_to_le16(conn->handle);
1204 dc.reason = 0x15; /* Terminated due to Power Off */
1205 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1206 break;
1207 case BT_CONNECT:
1208 if (conn->type == LE_LINK)
1209 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1210 0, NULL);
1211 else if (conn->type == ACL_LINK)
1212 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1213 6, &conn->dst);
1214 break;
1215 case BT_CONNECT2:
1216 bacpy(&rej.bdaddr, &conn->dst);
1217 rej.reason = 0x15; /* Terminated due to Power Off */
1218 if (conn->type == ACL_LINK)
1219 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1220 sizeof(rej), &rej);
1221 else if (conn->type == SCO_LINK)
1222 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1223 sizeof(rej), &rej);
1224 break;
1225 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001226 }
1227
1228 return hci_req_run(&req, clean_up_hci_complete);
1229}
1230
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001231static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001232 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001233{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001234 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001235 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001236 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001238 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001239
Johan Hedberga7e80f22013-01-09 16:05:19 +02001240 if (cp->val != 0x00 && cp->val != 0x01)
1241 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1242 MGMT_STATUS_INVALID_PARAMS);
1243
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001244 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001245
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001246 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1247 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1248 MGMT_STATUS_BUSY);
1249 goto failed;
1250 }
1251
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001252 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1253 cancel_delayed_work(&hdev->power_off);
1254
1255 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001256 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1257 data, len);
1258 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001259 goto failed;
1260 }
1261 }
1262
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001263 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001264 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001265 goto failed;
1266 }
1267
Johan Hedberg03811012010-12-08 00:21:06 +02001268 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1269 if (!cmd) {
1270 err = -ENOMEM;
1271 goto failed;
1272 }
1273
Johan Hedberg8b064a32014-02-24 14:52:22 +02001274 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001275 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001276 err = 0;
1277 } else {
1278 /* Disconnect connections, stop scans, etc */
1279 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001280 if (!err)
1281 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1282 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001283
Johan Hedberg8b064a32014-02-24 14:52:22 +02001284 /* ENODATA means there were no HCI commands queued */
1285 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001286 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001287 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1288 err = 0;
1289 }
1290 }
Johan Hedberg03811012010-12-08 00:21:06 +02001291
1292failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001293 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001294 return err;
1295}
1296
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001297static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1298 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001299{
1300 struct sk_buff *skb;
1301 struct mgmt_hdr *hdr;
1302
Andre Guedes790eff42012-06-07 19:05:46 -03001303 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001304 if (!skb)
1305 return -ENOMEM;
1306
1307 hdr = (void *) skb_put(skb, sizeof(*hdr));
1308 hdr->opcode = cpu_to_le16(event);
1309 if (hdev)
1310 hdr->index = cpu_to_le16(hdev->id);
1311 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001312 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001313 hdr->len = cpu_to_le16(data_len);
1314
1315 if (data)
1316 memcpy(skb_put(skb, data_len), data, data_len);
1317
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001318 /* Time stamp */
1319 __net_timestamp(skb);
1320
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001321 hci_send_to_control(skb, skip_sk);
1322 kfree_skb(skb);
1323
1324 return 0;
1325}
1326
1327static int new_settings(struct hci_dev *hdev, struct sock *skip)
1328{
1329 __le32 ev;
1330
1331 ev = cpu_to_le32(get_current_settings(hdev));
1332
1333 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1334}
1335
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001336struct cmd_lookup {
1337 struct sock *sk;
1338 struct hci_dev *hdev;
1339 u8 mgmt_status;
1340};
1341
1342static void settings_rsp(struct pending_cmd *cmd, void *data)
1343{
1344 struct cmd_lookup *match = data;
1345
1346 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1347
1348 list_del(&cmd->list);
1349
1350 if (match->sk == NULL) {
1351 match->sk = cmd->sk;
1352 sock_hold(match->sk);
1353 }
1354
1355 mgmt_pending_free(cmd);
1356}
1357
1358static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1359{
1360 u8 *status = data;
1361
1362 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1363 mgmt_pending_remove(cmd);
1364}
1365
Johan Hedberge6fe7982013-10-02 15:45:22 +03001366static u8 mgmt_bredr_support(struct hci_dev *hdev)
1367{
1368 if (!lmp_bredr_capable(hdev))
1369 return MGMT_STATUS_NOT_SUPPORTED;
1370 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1371 return MGMT_STATUS_REJECTED;
1372 else
1373 return MGMT_STATUS_SUCCESS;
1374}
1375
1376static u8 mgmt_le_support(struct hci_dev *hdev)
1377{
1378 if (!lmp_le_capable(hdev))
1379 return MGMT_STATUS_NOT_SUPPORTED;
1380 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1381 return MGMT_STATUS_REJECTED;
1382 else
1383 return MGMT_STATUS_SUCCESS;
1384}
1385
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001386static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1387{
1388 struct pending_cmd *cmd;
1389 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001390 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001391 bool changed;
1392
1393 BT_DBG("status 0x%02x", status);
1394
1395 hci_dev_lock(hdev);
1396
1397 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1398 if (!cmd)
1399 goto unlock;
1400
1401 if (status) {
1402 u8 mgmt_err = mgmt_status(status);
1403 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001404 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001405 goto remove_cmd;
1406 }
1407
1408 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001409 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001410 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1411 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001412
1413 if (hdev->discov_timeout > 0) {
1414 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1415 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1416 to);
1417 }
1418 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001419 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1420 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001421 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001422
1423 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1424
1425 if (changed)
1426 new_settings(hdev, cmd->sk);
1427
Marcel Holtmann970ba522013-10-15 06:33:57 -07001428 /* When the discoverable mode gets changed, make sure
1429 * that class of device has the limited discoverable
1430 * bit correctly set.
1431 */
1432 hci_req_init(&req, hdev);
1433 update_class(&req);
1434 hci_req_run(&req, NULL);
1435
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001436remove_cmd:
1437 mgmt_pending_remove(cmd);
1438
1439unlock:
1440 hci_dev_unlock(hdev);
1441}
1442
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001443static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001444 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001445{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001446 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001447 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001448 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001449 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001450 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001451 int err;
1452
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001453 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001454
Johan Hedberg9a43e252013-10-20 19:00:07 +03001455 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1456 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001457 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001458 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001459
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001460 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001461 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1462 MGMT_STATUS_INVALID_PARAMS);
1463
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001464 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001465
1466 /* Disabling discoverable requires that no timeout is set,
1467 * and enabling limited discoverable requires a timeout.
1468 */
1469 if ((cp->val == 0x00 && timeout > 0) ||
1470 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001471 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001472 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001473
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001474 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001475
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001476 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001477 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001478 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001479 goto failed;
1480 }
1481
1482 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001483 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001484 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001485 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001486 goto failed;
1487 }
1488
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001489 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001490 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001491 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001492 goto failed;
1493 }
1494
1495 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001496 bool changed = false;
1497
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001498 /* Setting limited discoverable when powered off is
1499 * not a valid operation since it requires a timeout
1500 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1501 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001502 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1503 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1504 changed = true;
1505 }
1506
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001507 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001508 if (err < 0)
1509 goto failed;
1510
1511 if (changed)
1512 err = new_settings(hdev, sk);
1513
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001514 goto failed;
1515 }
1516
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001517 /* If the current mode is the same, then just update the timeout
1518 * value with the new value. And if only the timeout gets updated,
1519 * then no need for any HCI transactions.
1520 */
1521 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1522 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1523 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001524 cancel_delayed_work(&hdev->discov_off);
1525 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001526
Marcel Holtmann36261542013-10-15 08:28:51 -07001527 if (cp->val && hdev->discov_timeout > 0) {
1528 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001529 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001530 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001531 }
1532
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001533 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001534 goto failed;
1535 }
1536
1537 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1538 if (!cmd) {
1539 err = -ENOMEM;
1540 goto failed;
1541 }
1542
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001543 /* Cancel any potential discoverable timeout that might be
1544 * still active and store new timeout value. The arming of
1545 * the timeout happens in the complete handler.
1546 */
1547 cancel_delayed_work(&hdev->discov_off);
1548 hdev->discov_timeout = timeout;
1549
Johan Hedbergb456f872013-10-19 23:38:22 +03001550 /* Limited discoverable mode */
1551 if (cp->val == 0x02)
1552 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1553 else
1554 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1555
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001556 hci_req_init(&req, hdev);
1557
Johan Hedberg9a43e252013-10-20 19:00:07 +03001558 /* The procedure for LE-only controllers is much simpler - just
1559 * update the advertising data.
1560 */
1561 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1562 goto update_ad;
1563
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001564 scan = SCAN_PAGE;
1565
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001566 if (cp->val) {
1567 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001568
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001569 if (cp->val == 0x02) {
1570 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001571 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001572 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1573 hci_cp.iac_lap[1] = 0x8b;
1574 hci_cp.iac_lap[2] = 0x9e;
1575 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1576 hci_cp.iac_lap[4] = 0x8b;
1577 hci_cp.iac_lap[5] = 0x9e;
1578 } else {
1579 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001580 hci_cp.num_iac = 1;
1581 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1582 hci_cp.iac_lap[1] = 0x8b;
1583 hci_cp.iac_lap[2] = 0x9e;
1584 }
1585
1586 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1587 (hci_cp.num_iac * 3) + 1, &hci_cp);
1588
1589 scan |= SCAN_INQUIRY;
1590 } else {
1591 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1592 }
1593
1594 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001595
Johan Hedberg9a43e252013-10-20 19:00:07 +03001596update_ad:
1597 update_adv_data(&req);
1598
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001599 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001600 if (err < 0)
1601 mgmt_pending_remove(cmd);
1602
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001603failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001604 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001605 return err;
1606}
1607
Johan Hedberg406d7802013-03-15 17:07:09 -05001608static void write_fast_connectable(struct hci_request *req, bool enable)
1609{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001610 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001611 struct hci_cp_write_page_scan_activity acp;
1612 u8 type;
1613
Johan Hedberg547003b2013-10-21 16:51:53 +03001614 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1615 return;
1616
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001617 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1618 return;
1619
Johan Hedberg406d7802013-03-15 17:07:09 -05001620 if (enable) {
1621 type = PAGE_SCAN_TYPE_INTERLACED;
1622
1623 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001624 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001625 } else {
1626 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1627
1628 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001629 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001630 }
1631
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001632 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001633
Johan Hedbergbd98b992013-03-15 17:07:13 -05001634 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1635 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1636 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1637 sizeof(acp), &acp);
1638
1639 if (hdev->page_scan_type != type)
1640 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001641}
1642
Johan Hedberg2b76f452013-03-15 17:07:04 -05001643static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1644{
1645 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001646 struct mgmt_mode *cp;
1647 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001648
1649 BT_DBG("status 0x%02x", status);
1650
1651 hci_dev_lock(hdev);
1652
1653 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1654 if (!cmd)
1655 goto unlock;
1656
Johan Hedberg37438c12013-10-14 16:20:05 +03001657 if (status) {
1658 u8 mgmt_err = mgmt_status(status);
1659 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1660 goto remove_cmd;
1661 }
1662
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001663 cp = cmd->param;
1664 if (cp->val)
1665 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1666 else
1667 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1668
Johan Hedberg2b76f452013-03-15 17:07:04 -05001669 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1670
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001671 if (changed)
1672 new_settings(hdev, cmd->sk);
1673
Johan Hedberg37438c12013-10-14 16:20:05 +03001674remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001675 mgmt_pending_remove(cmd);
1676
1677unlock:
1678 hci_dev_unlock(hdev);
1679}
1680
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001681static int set_connectable_update_settings(struct hci_dev *hdev,
1682 struct sock *sk, u8 val)
1683{
1684 bool changed = false;
1685 int err;
1686
1687 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1688 changed = true;
1689
1690 if (val) {
1691 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1692 } else {
1693 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1694 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1695 }
1696
1697 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1698 if (err < 0)
1699 return err;
1700
1701 if (changed)
1702 return new_settings(hdev, sk);
1703
1704 return 0;
1705}
1706
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001707static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001708 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001709{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001710 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001711 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001712 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001713 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001714 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001715
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001716 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001717
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001718 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1719 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001720 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001721 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001722
Johan Hedberga7e80f22013-01-09 16:05:19 +02001723 if (cp->val != 0x00 && cp->val != 0x01)
1724 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1725 MGMT_STATUS_INVALID_PARAMS);
1726
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001727 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001728
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001729 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001730 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001731 goto failed;
1732 }
1733
1734 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001735 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001736 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001737 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001738 goto failed;
1739 }
1740
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001741 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1742 if (!cmd) {
1743 err = -ENOMEM;
1744 goto failed;
1745 }
1746
Johan Hedberg2b76f452013-03-15 17:07:04 -05001747 hci_req_init(&req, hdev);
1748
Johan Hedberg9a43e252013-10-20 19:00:07 +03001749 /* If BR/EDR is not enabled and we disable advertising as a
1750 * by-product of disabling connectable, we need to update the
1751 * advertising flags.
1752 */
1753 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1754 if (!cp->val) {
1755 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1756 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1757 }
1758 update_adv_data(&req);
1759 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001760 if (cp->val) {
1761 scan = SCAN_PAGE;
1762 } else {
1763 scan = 0;
1764
1765 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001766 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001767 cancel_delayed_work(&hdev->discov_off);
1768 }
1769
1770 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1771 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001772
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001773 /* If we're going from non-connectable to connectable or
1774 * vice-versa when fast connectable is enabled ensure that fast
1775 * connectable gets disabled. write_fast_connectable won't do
1776 * anything if the page scan parameters are already what they
1777 * should be.
1778 */
1779 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001780 write_fast_connectable(&req, false);
1781
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001782 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1783 hci_conn_num(hdev, LE_LINK) == 0) {
1784 disable_advertising(&req);
1785 enable_advertising(&req);
1786 }
1787
Johan Hedberg2b76f452013-03-15 17:07:04 -05001788 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001789 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001790 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001791 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001792 err = set_connectable_update_settings(hdev, sk,
1793 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001794 goto failed;
1795 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001796
1797failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001798 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001799 return err;
1800}
1801
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001802static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001803 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001804{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001805 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001806 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001807 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001808
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001809 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001810
Johan Hedberga7e80f22013-01-09 16:05:19 +02001811 if (cp->val != 0x00 && cp->val != 0x01)
1812 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1813 MGMT_STATUS_INVALID_PARAMS);
1814
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001815 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001816
1817 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001818 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001819 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001820 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001821
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001822 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001823 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001824 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001825
Marcel Holtmann55594352013-10-06 16:11:57 -07001826 if (changed)
1827 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001828
Marcel Holtmann55594352013-10-06 16:11:57 -07001829unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001830 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001831 return err;
1832}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001833
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001834static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1835 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001836{
1837 struct mgmt_mode *cp = data;
1838 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001839 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001840 int err;
1841
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001842 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001843
Johan Hedberge6fe7982013-10-02 15:45:22 +03001844 status = mgmt_bredr_support(hdev);
1845 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001846 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001847 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001848
Johan Hedberga7e80f22013-01-09 16:05:19 +02001849 if (cp->val != 0x00 && cp->val != 0x01)
1850 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1851 MGMT_STATUS_INVALID_PARAMS);
1852
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001853 hci_dev_lock(hdev);
1854
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001855 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001856 bool changed = false;
1857
1858 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001859 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001860 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1861 changed = true;
1862 }
1863
1864 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1865 if (err < 0)
1866 goto failed;
1867
1868 if (changed)
1869 err = new_settings(hdev, sk);
1870
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001871 goto failed;
1872 }
1873
1874 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001875 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001876 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001877 goto failed;
1878 }
1879
1880 val = !!cp->val;
1881
1882 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1883 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1884 goto failed;
1885 }
1886
1887 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1888 if (!cmd) {
1889 err = -ENOMEM;
1890 goto failed;
1891 }
1892
1893 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1894 if (err < 0) {
1895 mgmt_pending_remove(cmd);
1896 goto failed;
1897 }
1898
1899failed:
1900 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001901 return err;
1902}
1903
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001904static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001905{
1906 struct mgmt_mode *cp = data;
1907 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001908 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001909 int err;
1910
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001911 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001912
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001913 status = mgmt_bredr_support(hdev);
1914 if (status)
1915 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1916
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001917 if (!lmp_ssp_capable(hdev))
1918 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1919 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001920
Johan Hedberga7e80f22013-01-09 16:05:19 +02001921 if (cp->val != 0x00 && cp->val != 0x01)
1922 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1923 MGMT_STATUS_INVALID_PARAMS);
1924
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001925 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001926
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001927 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001928 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001929
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001930 if (cp->val) {
1931 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1932 &hdev->dev_flags);
1933 } else {
1934 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1935 &hdev->dev_flags);
1936 if (!changed)
1937 changed = test_and_clear_bit(HCI_HS_ENABLED,
1938 &hdev->dev_flags);
1939 else
1940 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001941 }
1942
1943 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1944 if (err < 0)
1945 goto failed;
1946
1947 if (changed)
1948 err = new_settings(hdev, sk);
1949
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001950 goto failed;
1951 }
1952
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001953 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1954 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001955 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1956 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001957 goto failed;
1958 }
1959
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001960 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001961 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1962 goto failed;
1963 }
1964
1965 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1966 if (!cmd) {
1967 err = -ENOMEM;
1968 goto failed;
1969 }
1970
Johan Hedberg37699722014-06-24 14:00:27 +03001971 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
1972 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
1973 sizeof(cp->val), &cp->val);
1974
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001975 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001976 if (err < 0) {
1977 mgmt_pending_remove(cmd);
1978 goto failed;
1979 }
1980
1981failed:
1982 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001983 return err;
1984}
1985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001986static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001987{
1988 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001989 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001990 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001991 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001992
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001993 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001994
Johan Hedberge6fe7982013-10-02 15:45:22 +03001995 status = mgmt_bredr_support(hdev);
1996 if (status)
1997 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001998
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001999 if (!lmp_ssp_capable(hdev))
2000 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2001 MGMT_STATUS_NOT_SUPPORTED);
2002
2003 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2004 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2005 MGMT_STATUS_REJECTED);
2006
Johan Hedberga7e80f22013-01-09 16:05:19 +02002007 if (cp->val != 0x00 && cp->val != 0x01)
2008 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2009 MGMT_STATUS_INVALID_PARAMS);
2010
Marcel Holtmannee392692013-10-01 22:59:23 -07002011 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002012
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002013 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002014 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002015 } else {
2016 if (hdev_is_powered(hdev)) {
2017 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2018 MGMT_STATUS_REJECTED);
2019 goto unlock;
2020 }
2021
Marcel Holtmannee392692013-10-01 22:59:23 -07002022 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002023 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2026 if (err < 0)
2027 goto unlock;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
2032unlock:
2033 hci_dev_unlock(hdev);
2034 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002035}
2036
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002037static void le_enable_complete(struct hci_dev *hdev, u8 status)
2038{
2039 struct cmd_lookup match = { NULL, hdev };
2040
2041 if (status) {
2042 u8 mgmt_err = mgmt_status(status);
2043
2044 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2045 &mgmt_err);
2046 return;
2047 }
2048
2049 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2050
2051 new_settings(hdev, match.sk);
2052
2053 if (match.sk)
2054 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002055
2056 /* Make sure the controller has a good default for
2057 * advertising data. Restrict the update to when LE
2058 * has actually been enabled. During power on, the
2059 * update in powered_update_hci will take care of it.
2060 */
2061 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2062 struct hci_request req;
2063
2064 hci_dev_lock(hdev);
2065
2066 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002067 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002068 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002069 hci_req_run(&req, NULL);
2070
2071 hci_dev_unlock(hdev);
2072 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002073}
2074
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002075static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002076{
2077 struct mgmt_mode *cp = data;
2078 struct hci_cp_write_le_host_supported hci_cp;
2079 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002080 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002081 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002082 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002083
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002084 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 if (!lmp_le_capable(hdev))
2087 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2088 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002089
Johan Hedberga7e80f22013-01-09 16:05:19 +02002090 if (cp->val != 0x00 && cp->val != 0x01)
2091 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2092 MGMT_STATUS_INVALID_PARAMS);
2093
Johan Hedbergc73eee92013-04-19 18:35:21 +03002094 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002095 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002096 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2097 MGMT_STATUS_REJECTED);
2098
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002099 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002100
2101 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002102 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002103
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002104 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002105 bool changed = false;
2106
2107 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2108 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2109 changed = true;
2110 }
2111
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002112 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2113 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002114 changed = true;
2115 }
2116
Johan Hedberg06199cf2012-02-22 16:37:11 +02002117 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2118 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002119 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002120
2121 if (changed)
2122 err = new_settings(hdev, sk);
2123
Johan Hedberg1de028c2012-02-29 19:55:35 -08002124 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002125 }
2126
Johan Hedberg4375f102013-09-25 13:26:10 +03002127 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2128 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002129 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002130 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002131 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002132 }
2133
2134 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2135 if (!cmd) {
2136 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002137 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002138 }
2139
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002140 hci_req_init(&req, hdev);
2141
Johan Hedberg06199cf2012-02-22 16:37:11 +02002142 memset(&hci_cp, 0, sizeof(hci_cp));
2143
2144 if (val) {
2145 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002146 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002147 } else {
2148 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2149 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002150 }
2151
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002152 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2153 &hci_cp);
2154
2155 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302156 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002157 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002158
Johan Hedberg1de028c2012-02-29 19:55:35 -08002159unlock:
2160 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002161 return err;
2162}
2163
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002164/* This is a helper function to test for pending mgmt commands that can
2165 * cause CoD or EIR HCI commands. We can only allow one such pending
2166 * mgmt command at a time since otherwise we cannot easily track what
2167 * the current values are, will be, and based on that calculate if a new
2168 * HCI command needs to be sent and if yes with what value.
2169 */
2170static bool pending_eir_or_class(struct hci_dev *hdev)
2171{
2172 struct pending_cmd *cmd;
2173
2174 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2175 switch (cmd->opcode) {
2176 case MGMT_OP_ADD_UUID:
2177 case MGMT_OP_REMOVE_UUID:
2178 case MGMT_OP_SET_DEV_CLASS:
2179 case MGMT_OP_SET_POWERED:
2180 return true;
2181 }
2182 }
2183
2184 return false;
2185}
2186
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002187static const u8 bluetooth_base_uuid[] = {
2188 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2189 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190};
2191
2192static u8 get_uuid_size(const u8 *uuid)
2193{
2194 u32 val;
2195
2196 if (memcmp(uuid, bluetooth_base_uuid, 12))
2197 return 128;
2198
2199 val = get_unaligned_le32(&uuid[12]);
2200 if (val > 0xffff)
2201 return 32;
2202
2203 return 16;
2204}
2205
Johan Hedberg92da6092013-03-15 17:06:55 -05002206static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2207{
2208 struct pending_cmd *cmd;
2209
2210 hci_dev_lock(hdev);
2211
2212 cmd = mgmt_pending_find(mgmt_op, hdev);
2213 if (!cmd)
2214 goto unlock;
2215
2216 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2217 hdev->dev_class, 3);
2218
2219 mgmt_pending_remove(cmd);
2220
2221unlock:
2222 hci_dev_unlock(hdev);
2223}
2224
2225static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2226{
2227 BT_DBG("status 0x%02x", status);
2228
2229 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2230}
2231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002232static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002233{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002234 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002235 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002236 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002237 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002238 int err;
2239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002241
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002242 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002243
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002244 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002245 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002246 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002247 goto failed;
2248 }
2249
Andre Guedes92c4c202012-06-07 19:05:44 -03002250 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002251 if (!uuid) {
2252 err = -ENOMEM;
2253 goto failed;
2254 }
2255
2256 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002257 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002258 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002259
Johan Hedbergde66aa62013-01-27 00:31:27 +02002260 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002261
Johan Hedberg890ea892013-03-15 17:06:52 -05002262 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002263
Johan Hedberg890ea892013-03-15 17:06:52 -05002264 update_class(&req);
2265 update_eir(&req);
2266
Johan Hedberg92da6092013-03-15 17:06:55 -05002267 err = hci_req_run(&req, add_uuid_complete);
2268 if (err < 0) {
2269 if (err != -ENODATA)
2270 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002272 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002273 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002274 goto failed;
2275 }
2276
2277 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002278 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002279 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002280 goto failed;
2281 }
2282
2283 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002284
2285failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002286 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002287 return err;
2288}
2289
Johan Hedberg24b78d02012-02-23 23:24:30 +02002290static bool enable_service_cache(struct hci_dev *hdev)
2291{
2292 if (!hdev_is_powered(hdev))
2293 return false;
2294
2295 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002296 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2297 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002298 return true;
2299 }
2300
2301 return false;
2302}
2303
Johan Hedberg92da6092013-03-15 17:06:55 -05002304static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2305{
2306 BT_DBG("status 0x%02x", status);
2307
2308 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2309}
2310
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002311static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002312 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002313{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002314 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002315 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002316 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002317 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 -05002318 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002319 int err, found;
2320
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002321 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002323 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002324
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002325 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002326 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002327 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002328 goto unlock;
2329 }
2330
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002331 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002332 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002333
Johan Hedberg24b78d02012-02-23 23:24:30 +02002334 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002335 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002336 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002337 goto unlock;
2338 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002339
Johan Hedberg9246a862012-02-23 21:33:16 +02002340 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002341 }
2342
2343 found = 0;
2344
Johan Hedberg056341c2013-01-27 00:31:30 +02002345 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002346 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2347 continue;
2348
2349 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002350 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002351 found++;
2352 }
2353
2354 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002355 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002356 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002357 goto unlock;
2358 }
2359
Johan Hedberg9246a862012-02-23 21:33:16 +02002360update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002361 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002362
Johan Hedberg890ea892013-03-15 17:06:52 -05002363 update_class(&req);
2364 update_eir(&req);
2365
Johan Hedberg92da6092013-03-15 17:06:55 -05002366 err = hci_req_run(&req, remove_uuid_complete);
2367 if (err < 0) {
2368 if (err != -ENODATA)
2369 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002370
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002371 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002372 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002373 goto unlock;
2374 }
2375
2376 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002377 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002378 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002379 goto unlock;
2380 }
2381
2382 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002383
2384unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002385 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002386 return err;
2387}
2388
Johan Hedberg92da6092013-03-15 17:06:55 -05002389static void set_class_complete(struct hci_dev *hdev, u8 status)
2390{
2391 BT_DBG("status 0x%02x", status);
2392
2393 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002397 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002399 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002401 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002402 int err;
2403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002405
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002406 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002407 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2408 MGMT_STATUS_NOT_SUPPORTED);
2409
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002410 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002411
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002412 if (pending_eir_or_class(hdev)) {
2413 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2414 MGMT_STATUS_BUSY);
2415 goto unlock;
2416 }
2417
2418 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2419 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2420 MGMT_STATUS_INVALID_PARAMS);
2421 goto unlock;
2422 }
2423
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002424 hdev->major_class = cp->major;
2425 hdev->minor_class = cp->minor;
2426
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002427 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002428 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002429 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002430 goto unlock;
2431 }
2432
Johan Hedberg890ea892013-03-15 17:06:52 -05002433 hci_req_init(&req, hdev);
2434
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002435 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002436 hci_dev_unlock(hdev);
2437 cancel_delayed_work_sync(&hdev->service_cache);
2438 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002439 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002440 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002441
Johan Hedberg890ea892013-03-15 17:06:52 -05002442 update_class(&req);
2443
Johan Hedberg92da6092013-03-15 17:06:55 -05002444 err = hci_req_run(&req, set_class_complete);
2445 if (err < 0) {
2446 if (err != -ENODATA)
2447 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002449 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002450 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002451 goto unlock;
2452 }
2453
2454 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002455 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002456 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002457 goto unlock;
2458 }
2459
2460 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002461
Johan Hedbergb5235a62012-02-21 14:32:24 +02002462unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002463 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002464 return err;
2465}
2466
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002467static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002468 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002469{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002470 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002471 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002472 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002473 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002474
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002475 BT_DBG("request for %s", hdev->name);
2476
2477 if (!lmp_bredr_capable(hdev))
2478 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2479 MGMT_STATUS_NOT_SUPPORTED);
2480
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002481 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002482
Johan Hedberg86742e12011-11-07 23:13:38 +02002483 expected_len = sizeof(*cp) + key_count *
2484 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002485 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002486 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002487 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002488 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002489 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002490 }
2491
Johan Hedberg4ae14302013-01-20 14:27:13 +02002492 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2493 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2494 MGMT_STATUS_INVALID_PARAMS);
2495
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002496 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002497 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002498
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002499 for (i = 0; i < key_count; i++) {
2500 struct mgmt_link_key_info *key = &cp->keys[i];
2501
Marcel Holtmann8e991132014-01-10 02:07:25 -08002502 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002503 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2504 MGMT_STATUS_INVALID_PARAMS);
2505 }
2506
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002507 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002508
2509 hci_link_keys_clear(hdev);
2510
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002511 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002512 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2513 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002514 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002515 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2516 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002517
2518 if (changed)
2519 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002520
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002521 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002522 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002523
Johan Hedberg58e92932014-06-24 14:00:26 +03002524 /* Always ignore debug keys and require a new pairing if
2525 * the user wants to use them.
2526 */
2527 if (key->type == HCI_LK_DEBUG_COMBINATION)
2528 continue;
2529
Johan Hedberg7652ff62014-06-24 13:15:49 +03002530 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2531 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002532 }
2533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002535
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002536 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002537
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002538 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002539}
2540
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002541static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002542 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002543{
2544 struct mgmt_ev_device_unpaired ev;
2545
2546 bacpy(&ev.addr.bdaddr, bdaddr);
2547 ev.addr.type = addr_type;
2548
2549 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002551}
2552
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002553static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002554 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002555{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002556 struct mgmt_cp_unpair_device *cp = data;
2557 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002558 struct hci_cp_disconnect dc;
2559 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002560 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002561 int err;
2562
Johan Hedberga8a1d192011-11-10 15:54:38 +02002563 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002564 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2565 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002566
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002567 if (!bdaddr_type_is_valid(cp->addr.type))
2568 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2569 MGMT_STATUS_INVALID_PARAMS,
2570 &rp, sizeof(rp));
2571
Johan Hedberg118da702013-01-20 14:27:20 +02002572 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2573 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2574 MGMT_STATUS_INVALID_PARAMS,
2575 &rp, sizeof(rp));
2576
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002577 hci_dev_lock(hdev);
2578
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002579 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002580 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002581 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002582 goto unlock;
2583 }
2584
Johan Hedberge0b2b272014-02-18 17:14:31 +02002585 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002586 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002587 } else {
2588 u8 addr_type;
2589
2590 if (cp->addr.type == BDADDR_LE_PUBLIC)
2591 addr_type = ADDR_LE_DEV_PUBLIC;
2592 else
2593 addr_type = ADDR_LE_DEV_RANDOM;
2594
Johan Hedberga7ec7332014-02-18 17:14:35 +02002595 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2596
Andre Guedesa9b0a042014-02-26 20:21:52 -03002597 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2598
Johan Hedberge0b2b272014-02-18 17:14:31 +02002599 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2600 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002601
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002602 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002603 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002604 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002605 goto unlock;
2606 }
2607
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002608 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002609 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002610 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002611 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002612 else
2613 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002614 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002615 } else {
2616 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002617 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002618
Johan Hedberga8a1d192011-11-10 15:54:38 +02002619 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002620 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002621 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002622 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002623 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624 }
2625
Johan Hedberg124f6e32012-02-09 13:50:12 +02002626 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002627 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002628 if (!cmd) {
2629 err = -ENOMEM;
2630 goto unlock;
2631 }
2632
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002633 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002634 dc.reason = 0x13; /* Remote User Terminated Connection */
2635 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2636 if (err < 0)
2637 mgmt_pending_remove(cmd);
2638
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002640 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002641 return err;
2642}
2643
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002644static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002645 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002646{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002647 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002648 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002649 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002650 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002651 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002652 int err;
2653
2654 BT_DBG("");
2655
Johan Hedberg06a63b12013-01-20 14:27:21 +02002656 memset(&rp, 0, sizeof(rp));
2657 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2658 rp.addr.type = cp->addr.type;
2659
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002660 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002661 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2662 MGMT_STATUS_INVALID_PARAMS,
2663 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002664
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002665 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002666
2667 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002668 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2669 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002670 goto failed;
2671 }
2672
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002673 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002674 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2675 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002676 goto failed;
2677 }
2678
Andre Guedes591f47f2012-04-24 21:02:49 -03002679 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002680 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2681 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002682 else
2683 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002684
Vishal Agarwalf9607272012-06-13 05:32:43 +05302685 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002686 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2687 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002688 goto failed;
2689 }
2690
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002691 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002692 if (!cmd) {
2693 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002694 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002695 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002696
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002697 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002698 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002699
2700 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2701 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002702 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002703
2704failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002705 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002706 return err;
2707}
2708
Andre Guedes57c14772012-04-24 21:02:50 -03002709static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002710{
2711 switch (link_type) {
2712 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002713 switch (addr_type) {
2714 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002715 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002716
Johan Hedberg48264f02011-11-09 13:58:58 +02002717 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002718 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002719 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002720 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002721
Johan Hedberg4c659c32011-11-07 23:13:39 +02002722 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002723 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002724 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002725 }
2726}
2727
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002728static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2729 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002730{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002731 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002732 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002733 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002734 int err;
2735 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002736
2737 BT_DBG("");
2738
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002739 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002740
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002741 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002742 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002743 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002744 goto unlock;
2745 }
2746
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002747 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002748 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2749 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002750 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002751 }
2752
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002753 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002754 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002755 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002756 err = -ENOMEM;
2757 goto unlock;
2758 }
2759
Johan Hedberg2784eb42011-01-21 13:56:35 +02002760 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002761 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002762 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2763 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002764 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002765 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002766 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002767 continue;
2768 i++;
2769 }
2770
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002771 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002772
Johan Hedberg4c659c32011-11-07 23:13:39 +02002773 /* Recalculate length in case of filtered SCO connections, etc */
2774 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002775
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002776 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002777 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002778
Johan Hedberga38528f2011-01-22 06:46:43 +02002779 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002780
2781unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002782 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002783 return err;
2784}
2785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002786static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002787 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002788{
2789 struct pending_cmd *cmd;
2790 int err;
2791
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002792 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002793 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002794 if (!cmd)
2795 return -ENOMEM;
2796
Johan Hedbergd8457692012-02-17 14:24:57 +02002797 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002798 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002799 if (err < 0)
2800 mgmt_pending_remove(cmd);
2801
2802 return err;
2803}
2804
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002805static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002806 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002807{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002808 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002809 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002810 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002811 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002812 int err;
2813
2814 BT_DBG("");
2815
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002816 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002817
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002818 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002819 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002820 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002821 goto failed;
2822 }
2823
Johan Hedbergd8457692012-02-17 14:24:57 +02002824 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002825 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002826 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002827 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002828 goto failed;
2829 }
2830
2831 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002832 struct mgmt_cp_pin_code_neg_reply ncp;
2833
2834 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002835
2836 BT_ERR("PIN code is not 16 bytes long");
2837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002838 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002839 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002840 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002841 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002842
2843 goto failed;
2844 }
2845
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002846 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002847 if (!cmd) {
2848 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002849 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002850 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002851
Johan Hedbergd8457692012-02-17 14:24:57 +02002852 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002853 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002854 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002855
2856 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2857 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002858 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002859
2860failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002861 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002862 return err;
2863}
2864
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002865static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2866 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002867{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002868 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002869
2870 BT_DBG("");
2871
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002872 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2873 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2874 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2875
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002876 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002877
2878 hdev->io_capability = cp->io_capability;
2879
2880 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002881 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002882
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002883 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002884
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002885 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2886 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002887}
2888
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002889static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002890{
2891 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002892 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002893
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002894 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002895 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2896 continue;
2897
Johan Hedberge9a416b2011-02-19 12:05:56 -03002898 if (cmd->user_data != conn)
2899 continue;
2900
2901 return cmd;
2902 }
2903
2904 return NULL;
2905}
2906
2907static void pairing_complete(struct pending_cmd *cmd, u8 status)
2908{
2909 struct mgmt_rp_pair_device rp;
2910 struct hci_conn *conn = cmd->user_data;
2911
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002912 bacpy(&rp.addr.bdaddr, &conn->dst);
2913 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002914
Johan Hedbergaee9b212012-02-18 15:07:59 +02002915 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002916 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002917
2918 /* So we don't get further callbacks for this connection */
2919 conn->connect_cfm_cb = NULL;
2920 conn->security_cfm_cb = NULL;
2921 conn->disconn_cfm_cb = NULL;
2922
David Herrmann76a68ba2013-04-06 20:28:37 +02002923 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002924
Johan Hedberga664b5b2011-02-19 12:06:02 -03002925 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002926}
2927
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002928void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2929{
2930 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2931 struct pending_cmd *cmd;
2932
2933 cmd = find_pairing(conn);
2934 if (cmd)
2935 pairing_complete(cmd, status);
2936}
2937
Johan Hedberge9a416b2011-02-19 12:05:56 -03002938static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2939{
2940 struct pending_cmd *cmd;
2941
2942 BT_DBG("status %u", status);
2943
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002944 cmd = find_pairing(conn);
2945 if (!cmd)
2946 BT_DBG("Unable to find a pending command");
2947 else
Johan Hedberge2113262012-02-18 15:20:03 +02002948 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002949}
2950
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002951static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302952{
2953 struct pending_cmd *cmd;
2954
2955 BT_DBG("status %u", status);
2956
2957 if (!status)
2958 return;
2959
2960 cmd = find_pairing(conn);
2961 if (!cmd)
2962 BT_DBG("Unable to find a pending command");
2963 else
2964 pairing_complete(cmd, mgmt_status(status));
2965}
2966
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002969{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002970 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002971 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002972 struct pending_cmd *cmd;
2973 u8 sec_level, auth_type;
2974 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002975 int err;
2976
2977 BT_DBG("");
2978
Szymon Jancf950a30e2013-01-18 12:48:07 +01002979 memset(&rp, 0, sizeof(rp));
2980 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2981 rp.addr.type = cp->addr.type;
2982
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002983 if (!bdaddr_type_is_valid(cp->addr.type))
2984 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2985 MGMT_STATUS_INVALID_PARAMS,
2986 &rp, sizeof(rp));
2987
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002988 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2989 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2990 MGMT_STATUS_INVALID_PARAMS,
2991 &rp, sizeof(rp));
2992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002993 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002994
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002995 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002996 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2997 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002998 goto unlock;
2999 }
3000
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003001 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003002 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003003
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003004 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003005 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3006 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003007 } else {
3008 u8 addr_type;
3009
3010 /* Convert from L2CAP channel address type to HCI address type
3011 */
3012 if (cp->addr.type == BDADDR_LE_PUBLIC)
3013 addr_type = ADDR_LE_DEV_PUBLIC;
3014 else
3015 addr_type = ADDR_LE_DEV_RANDOM;
3016
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003017 /* When pairing a new device, it is expected to remember
3018 * this device for future connections. Adding the connection
3019 * parameter information ahead of time allows tracking
3020 * of the slave preferred values and will speed up any
3021 * further connection establishment.
3022 *
3023 * If connection parameters already exist, then they
3024 * will be kept and this function does nothing.
3025 */
3026 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3027
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003028 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003029 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003030 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003031
Ville Tervo30e76272011-02-22 16:10:53 -03003032 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003033 int status;
3034
3035 if (PTR_ERR(conn) == -EBUSY)
3036 status = MGMT_STATUS_BUSY;
3037 else
3038 status = MGMT_STATUS_CONNECT_FAILED;
3039
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003040 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003041 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003042 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003043 goto unlock;
3044 }
3045
3046 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003047 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003048 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003049 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003050 goto unlock;
3051 }
3052
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003053 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003054 if (!cmd) {
3055 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003056 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003057 goto unlock;
3058 }
3059
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003060 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003061 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003062 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003063 conn->security_cfm_cb = pairing_complete_cb;
3064 conn->disconn_cfm_cb = pairing_complete_cb;
3065 } else {
3066 conn->connect_cfm_cb = le_pairing_complete_cb;
3067 conn->security_cfm_cb = le_pairing_complete_cb;
3068 conn->disconn_cfm_cb = le_pairing_complete_cb;
3069 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003070
Johan Hedberge9a416b2011-02-19 12:05:56 -03003071 conn->io_capability = cp->io_cap;
3072 cmd->user_data = conn;
3073
3074 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003075 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003076 pairing_complete(cmd, 0);
3077
3078 err = 0;
3079
3080unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003081 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003082 return err;
3083}
3084
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003085static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3086 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003087{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003088 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003089 struct pending_cmd *cmd;
3090 struct hci_conn *conn;
3091 int err;
3092
3093 BT_DBG("");
3094
Johan Hedberg28424702012-02-02 04:02:29 +02003095 hci_dev_lock(hdev);
3096
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003097 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003098 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003099 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003100 goto unlock;
3101 }
3102
Johan Hedberg28424702012-02-02 04:02:29 +02003103 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3104 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003105 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003106 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003107 goto unlock;
3108 }
3109
3110 conn = cmd->user_data;
3111
3112 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003113 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003114 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003115 goto unlock;
3116 }
3117
3118 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3119
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003120 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003121 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003122unlock:
3123 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003124 return err;
3125}
3126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003127static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003128 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003130{
Johan Hedberga5c29682011-02-19 12:05:57 -03003131 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003132 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003133 int err;
3134
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003135 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003136
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003137 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003138 err = cmd_complete(sk, hdev->id, mgmt_op,
3139 MGMT_STATUS_NOT_POWERED, addr,
3140 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003141 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003142 }
3143
Johan Hedberg1707c602013-03-15 17:07:15 -05003144 if (addr->type == BDADDR_BREDR)
3145 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003146 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003147 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003148
Johan Hedberg272d90d2012-02-09 15:26:12 +02003149 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003150 err = cmd_complete(sk, hdev->id, mgmt_op,
3151 MGMT_STATUS_NOT_CONNECTED, addr,
3152 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003153 goto done;
3154 }
3155
Johan Hedberg1707c602013-03-15 17:07:15 -05003156 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003157 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003158 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003159 err = cmd_complete(sk, hdev->id, mgmt_op,
3160 MGMT_STATUS_SUCCESS, addr,
3161 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003162 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003163 err = cmd_complete(sk, hdev->id, mgmt_op,
3164 MGMT_STATUS_FAILED, addr,
3165 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003166
Brian Gix47c15e22011-11-16 13:53:14 -08003167 goto done;
3168 }
3169
Johan Hedberg1707c602013-03-15 17:07:15 -05003170 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003171 if (!cmd) {
3172 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003173 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003174 }
3175
Brian Gix0df4c182011-11-16 13:53:13 -08003176 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003177 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3178 struct hci_cp_user_passkey_reply cp;
3179
Johan Hedberg1707c602013-03-15 17:07:15 -05003180 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003181 cp.passkey = passkey;
3182 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3183 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003184 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3185 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003186
Johan Hedberga664b5b2011-02-19 12:06:02 -03003187 if (err < 0)
3188 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003189
Brian Gix0df4c182011-11-16 13:53:13 -08003190done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003191 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003192 return err;
3193}
3194
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303195static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3196 void *data, u16 len)
3197{
3198 struct mgmt_cp_pin_code_neg_reply *cp = data;
3199
3200 BT_DBG("");
3201
Johan Hedberg1707c602013-03-15 17:07:15 -05003202 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303203 MGMT_OP_PIN_CODE_NEG_REPLY,
3204 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3205}
3206
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003207static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3208 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003209{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003210 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003211
3212 BT_DBG("");
3213
3214 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003215 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003217
Johan Hedberg1707c602013-03-15 17:07:15 -05003218 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003219 MGMT_OP_USER_CONFIRM_REPLY,
3220 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003221}
3222
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003223static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003224 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003225{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003226 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003227
3228 BT_DBG("");
3229
Johan Hedberg1707c602013-03-15 17:07:15 -05003230 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003231 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3232 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003233}
3234
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003235static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3236 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003237{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003238 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003239
3240 BT_DBG("");
3241
Johan Hedberg1707c602013-03-15 17:07:15 -05003242 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003243 MGMT_OP_USER_PASSKEY_REPLY,
3244 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003245}
3246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003247static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003248 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003249{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003250 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003251
3252 BT_DBG("");
3253
Johan Hedberg1707c602013-03-15 17:07:15 -05003254 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003255 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3256 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003257}
3258
Johan Hedberg13928972013-03-15 17:07:00 -05003259static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003260{
Johan Hedberg13928972013-03-15 17:07:00 -05003261 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003262 struct hci_cp_write_local_name cp;
3263
Johan Hedberg13928972013-03-15 17:07:00 -05003264 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003265
Johan Hedberg890ea892013-03-15 17:06:52 -05003266 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003267}
3268
Johan Hedberg13928972013-03-15 17:07:00 -05003269static void set_name_complete(struct hci_dev *hdev, u8 status)
3270{
3271 struct mgmt_cp_set_local_name *cp;
3272 struct pending_cmd *cmd;
3273
3274 BT_DBG("status 0x%02x", status);
3275
3276 hci_dev_lock(hdev);
3277
3278 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3279 if (!cmd)
3280 goto unlock;
3281
3282 cp = cmd->param;
3283
3284 if (status)
3285 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3286 mgmt_status(status));
3287 else
3288 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3289 cp, sizeof(*cp));
3290
3291 mgmt_pending_remove(cmd);
3292
3293unlock:
3294 hci_dev_unlock(hdev);
3295}
3296
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003297static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003298 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003299{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003300 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003301 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003302 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003303 int err;
3304
3305 BT_DBG("");
3306
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003307 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003308
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003309 /* If the old values are the same as the new ones just return a
3310 * direct command complete event.
3311 */
3312 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3313 !memcmp(hdev->short_name, cp->short_name,
3314 sizeof(hdev->short_name))) {
3315 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3316 data, len);
3317 goto failed;
3318 }
3319
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003320 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003321
Johan Hedbergb5235a62012-02-21 14:32:24 +02003322 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003323 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003324
3325 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003326 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003327 if (err < 0)
3328 goto failed;
3329
3330 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003332
Johan Hedbergb5235a62012-02-21 14:32:24 +02003333 goto failed;
3334 }
3335
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003336 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003337 if (!cmd) {
3338 err = -ENOMEM;
3339 goto failed;
3340 }
3341
Johan Hedberg13928972013-03-15 17:07:00 -05003342 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3343
Johan Hedberg890ea892013-03-15 17:06:52 -05003344 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003345
3346 if (lmp_bredr_capable(hdev)) {
3347 update_name(&req);
3348 update_eir(&req);
3349 }
3350
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003351 /* The name is stored in the scan response data and so
3352 * no need to udpate the advertising data here.
3353 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003354 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003355 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003356
Johan Hedberg13928972013-03-15 17:07:00 -05003357 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003358 if (err < 0)
3359 mgmt_pending_remove(cmd);
3360
3361failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003362 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003363 return err;
3364}
3365
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003366static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003367 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003368{
Szymon Jancc35938b2011-03-22 13:12:21 +01003369 struct pending_cmd *cmd;
3370 int err;
3371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003372 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003373
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003374 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003375
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003376 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003377 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003378 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003379 goto unlock;
3380 }
3381
Andre Guedes9a1a1992012-07-24 15:03:48 -03003382 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003383 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003384 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003385 goto unlock;
3386 }
3387
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003388 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003389 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003390 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003391 goto unlock;
3392 }
3393
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003394 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003395 if (!cmd) {
3396 err = -ENOMEM;
3397 goto unlock;
3398 }
3399
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003400 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3401 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3402 0, NULL);
3403 else
3404 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3405
Szymon Jancc35938b2011-03-22 13:12:21 +01003406 if (err < 0)
3407 mgmt_pending_remove(cmd);
3408
3409unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003410 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003411 return err;
3412}
3413
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003414static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003415 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003416{
Szymon Janc2763eda2011-03-22 13:12:22 +01003417 int err;
3418
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003419 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003420
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003421 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003422
Marcel Holtmannec109112014-01-10 02:07:30 -08003423 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3424 struct mgmt_cp_add_remote_oob_data *cp = data;
3425 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003426
Marcel Holtmannec109112014-01-10 02:07:30 -08003427 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3428 cp->hash, cp->randomizer);
3429 if (err < 0)
3430 status = MGMT_STATUS_FAILED;
3431 else
3432 status = MGMT_STATUS_SUCCESS;
3433
3434 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3435 status, &cp->addr, sizeof(cp->addr));
3436 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3437 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3438 u8 status;
3439
3440 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3441 cp->hash192,
3442 cp->randomizer192,
3443 cp->hash256,
3444 cp->randomizer256);
3445 if (err < 0)
3446 status = MGMT_STATUS_FAILED;
3447 else
3448 status = MGMT_STATUS_SUCCESS;
3449
3450 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3451 status, &cp->addr, sizeof(cp->addr));
3452 } else {
3453 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3454 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3455 MGMT_STATUS_INVALID_PARAMS);
3456 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003457
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003458 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003459 return err;
3460}
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003463 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003464{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003465 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003466 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003467 int err;
3468
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003469 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003470
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003471 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003472
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003473 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003474 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003475 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003476 else
Szymon Janca6785be2012-12-13 15:11:21 +01003477 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003481
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003482 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003483 return err;
3484}
3485
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003486static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3487{
3488 struct pending_cmd *cmd;
3489 u8 type;
3490 int err;
3491
3492 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3493
3494 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3495 if (!cmd)
3496 return -ENOENT;
3497
3498 type = hdev->discovery.type;
3499
3500 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3501 &type, sizeof(type));
3502 mgmt_pending_remove(cmd);
3503
3504 return err;
3505}
3506
Andre Guedes7c307722013-04-30 15:29:28 -03003507static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3508{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003509 unsigned long timeout = 0;
3510
Andre Guedes7c307722013-04-30 15:29:28 -03003511 BT_DBG("status %d", status);
3512
3513 if (status) {
3514 hci_dev_lock(hdev);
3515 mgmt_start_discovery_failed(hdev, status);
3516 hci_dev_unlock(hdev);
3517 return;
3518 }
3519
3520 hci_dev_lock(hdev);
3521 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3522 hci_dev_unlock(hdev);
3523
3524 switch (hdev->discovery.type) {
3525 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003526 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003527 break;
3528
3529 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003530 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003531 break;
3532
3533 case DISCOV_TYPE_BREDR:
3534 break;
3535
3536 default:
3537 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3538 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003539
3540 if (!timeout)
3541 return;
3542
3543 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003544}
3545
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003546static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003547 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003548{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003549 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003550 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003551 struct hci_cp_le_set_scan_param param_cp;
3552 struct hci_cp_le_set_scan_enable enable_cp;
3553 struct hci_cp_inquiry inq_cp;
3554 struct hci_request req;
3555 /* General inquiry access code (GIAC) */
3556 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003557 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003558 int err;
3559
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003560 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003561
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003562 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003563
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003564 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003565 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003566 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003567 goto failed;
3568 }
3569
Andre Guedes642be6c2012-03-21 00:03:37 -03003570 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3571 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3572 MGMT_STATUS_BUSY);
3573 goto failed;
3574 }
3575
Johan Hedbergff9ef572012-01-04 14:23:45 +02003576 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003577 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003578 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003579 goto failed;
3580 }
3581
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003582 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003583 if (!cmd) {
3584 err = -ENOMEM;
3585 goto failed;
3586 }
3587
Andre Guedes4aab14e2012-02-17 20:39:36 -03003588 hdev->discovery.type = cp->type;
3589
Andre Guedes7c307722013-04-30 15:29:28 -03003590 hci_req_init(&req, hdev);
3591
Andre Guedes4aab14e2012-02-17 20:39:36 -03003592 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003593 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003594 status = mgmt_bredr_support(hdev);
3595 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003596 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003597 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003598 mgmt_pending_remove(cmd);
3599 goto failed;
3600 }
3601
Andre Guedes7c307722013-04-30 15:29:28 -03003602 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3603 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3604 MGMT_STATUS_BUSY);
3605 mgmt_pending_remove(cmd);
3606 goto failed;
3607 }
3608
3609 hci_inquiry_cache_flush(hdev);
3610
3611 memset(&inq_cp, 0, sizeof(inq_cp));
3612 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003613 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003614 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003615 break;
3616
3617 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003618 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003619 status = mgmt_le_support(hdev);
3620 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003621 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003622 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003623 mgmt_pending_remove(cmd);
3624 goto failed;
3625 }
3626
Andre Guedes7c307722013-04-30 15:29:28 -03003627 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003628 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003629 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3630 MGMT_STATUS_NOT_SUPPORTED);
3631 mgmt_pending_remove(cmd);
3632 goto failed;
3633 }
3634
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003635 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003636 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3637 MGMT_STATUS_REJECTED);
3638 mgmt_pending_remove(cmd);
3639 goto failed;
3640 }
3641
Andre Guedesc54c3862014-02-26 20:21:50 -03003642 /* If controller is scanning, it means the background scanning
3643 * is running. Thus, we should temporarily stop it in order to
3644 * set the discovery scanning parameters.
3645 */
3646 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3647 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003648
3649 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003650
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003651 /* All active scans will be done with either a resolvable
3652 * private address (when privacy feature has been enabled)
3653 * or unresolvable private address.
3654 */
3655 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003656 if (err < 0) {
3657 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3658 MGMT_STATUS_FAILED);
3659 mgmt_pending_remove(cmd);
3660 goto failed;
3661 }
3662
Andre Guedes7c307722013-04-30 15:29:28 -03003663 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003664 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3665 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003666 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003667 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3668 &param_cp);
3669
3670 memset(&enable_cp, 0, sizeof(enable_cp));
3671 enable_cp.enable = LE_SCAN_ENABLE;
3672 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3673 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3674 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003675 break;
3676
Andre Guedesf39799f2012-02-17 20:39:35 -03003677 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003678 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3679 MGMT_STATUS_INVALID_PARAMS);
3680 mgmt_pending_remove(cmd);
3681 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003682 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003683
Andre Guedes7c307722013-04-30 15:29:28 -03003684 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003685 if (err < 0)
3686 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003687 else
3688 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003689
3690failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003691 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003692 return err;
3693}
3694
Andre Guedes1183fdc2013-04-30 15:29:35 -03003695static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3696{
3697 struct pending_cmd *cmd;
3698 int err;
3699
3700 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3701 if (!cmd)
3702 return -ENOENT;
3703
3704 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3705 &hdev->discovery.type, sizeof(hdev->discovery.type));
3706 mgmt_pending_remove(cmd);
3707
3708 return err;
3709}
3710
Andre Guedes0e05bba2013-04-30 15:29:33 -03003711static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3712{
3713 BT_DBG("status %d", status);
3714
3715 hci_dev_lock(hdev);
3716
3717 if (status) {
3718 mgmt_stop_discovery_failed(hdev, status);
3719 goto unlock;
3720 }
3721
3722 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3723
3724unlock:
3725 hci_dev_unlock(hdev);
3726}
3727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003728static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003729 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003730{
Johan Hedbergd9306502012-02-20 23:25:18 +02003731 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003732 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003733 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003734 int err;
3735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003736 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003737
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003738 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003739
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003740 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003741 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003742 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3743 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003744 goto unlock;
3745 }
3746
3747 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003748 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003749 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3750 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003751 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003752 }
3753
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003754 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003755 if (!cmd) {
3756 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003757 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003758 }
3759
Andre Guedes0e05bba2013-04-30 15:29:33 -03003760 hci_req_init(&req, hdev);
3761
Johan Hedberg21a60d32014-06-10 14:05:58 +03003762 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003763
Johan Hedberg21a60d32014-06-10 14:05:58 +03003764 err = hci_req_run(&req, stop_discovery_complete);
3765 if (!err) {
3766 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003767 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003768 }
3769
Johan Hedberg21a60d32014-06-10 14:05:58 +03003770 mgmt_pending_remove(cmd);
3771
3772 /* If no HCI commands were sent we're done */
3773 if (err == -ENODATA) {
3774 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3775 &mgmt_cp->type, sizeof(mgmt_cp->type));
3776 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3777 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003778
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003779unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003780 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003781 return err;
3782}
3783
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003784static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003785 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003786{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003787 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003788 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003789 int err;
3790
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003791 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003792
Johan Hedberg561aafb2012-01-04 13:31:59 +02003793 hci_dev_lock(hdev);
3794
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003795 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003796 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3797 MGMT_STATUS_FAILED, &cp->addr,
3798 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003799 goto failed;
3800 }
3801
Johan Hedberga198e7b2012-02-17 14:27:06 +02003802 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003803 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003804 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3805 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3806 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003807 goto failed;
3808 }
3809
3810 if (cp->name_known) {
3811 e->name_state = NAME_KNOWN;
3812 list_del(&e->list);
3813 } else {
3814 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003815 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003816 }
3817
Johan Hedberge3846622013-01-09 15:29:33 +02003818 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3819 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003820
3821failed:
3822 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003823 return err;
3824}
3825
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003826static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003827 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003828{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003829 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003830 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003831 int err;
3832
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003833 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003834
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003835 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003836 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3837 MGMT_STATUS_INVALID_PARAMS,
3838 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003839
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003840 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003841
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003842 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003843 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003844 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003845 goto done;
3846 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003847
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003848 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3849 sk);
3850 status = MGMT_STATUS_SUCCESS;
3851
3852done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003853 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003854 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003855
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003856 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003857
3858 return err;
3859}
3860
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003861static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003862 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003863{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003864 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003865 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003866 int err;
3867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003868 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003869
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003870 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003871 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3872 MGMT_STATUS_INVALID_PARAMS,
3873 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003874
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003875 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003876
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003877 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003878 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003879 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003880 goto done;
3881 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003882
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003883 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3884 sk);
3885 status = MGMT_STATUS_SUCCESS;
3886
3887done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003888 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003889 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003890
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003891 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003892
3893 return err;
3894}
3895
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003896static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3897 u16 len)
3898{
3899 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003900 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003901 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003902 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003903
3904 BT_DBG("%s", hdev->name);
3905
Szymon Jancc72d4b82012-03-16 16:02:57 +01003906 source = __le16_to_cpu(cp->source);
3907
3908 if (source > 0x0002)
3909 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3910 MGMT_STATUS_INVALID_PARAMS);
3911
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003912 hci_dev_lock(hdev);
3913
Szymon Jancc72d4b82012-03-16 16:02:57 +01003914 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003915 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3916 hdev->devid_product = __le16_to_cpu(cp->product);
3917 hdev->devid_version = __le16_to_cpu(cp->version);
3918
3919 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3920
Johan Hedberg890ea892013-03-15 17:06:52 -05003921 hci_req_init(&req, hdev);
3922 update_eir(&req);
3923 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003924
3925 hci_dev_unlock(hdev);
3926
3927 return err;
3928}
3929
Johan Hedberg4375f102013-09-25 13:26:10 +03003930static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3931{
3932 struct cmd_lookup match = { NULL, hdev };
3933
3934 if (status) {
3935 u8 mgmt_err = mgmt_status(status);
3936
3937 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3938 cmd_status_rsp, &mgmt_err);
3939 return;
3940 }
3941
3942 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3943 &match);
3944
3945 new_settings(hdev, match.sk);
3946
3947 if (match.sk)
3948 sock_put(match.sk);
3949}
3950
Marcel Holtmann21b51872013-10-10 09:47:53 -07003951static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3952 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003953{
3954 struct mgmt_mode *cp = data;
3955 struct pending_cmd *cmd;
3956 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003957 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003958 int err;
3959
3960 BT_DBG("request for %s", hdev->name);
3961
Johan Hedberge6fe7982013-10-02 15:45:22 +03003962 status = mgmt_le_support(hdev);
3963 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003964 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003965 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003966
3967 if (cp->val != 0x00 && cp->val != 0x01)
3968 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3969 MGMT_STATUS_INVALID_PARAMS);
3970
3971 hci_dev_lock(hdev);
3972
3973 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003974 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003975
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003976 /* The following conditions are ones which mean that we should
3977 * not do any HCI communication but directly send a mgmt
3978 * response to user space (after toggling the flag if
3979 * necessary).
3980 */
3981 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003982 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003983 bool changed = false;
3984
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003985 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3986 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003987 changed = true;
3988 }
3989
3990 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3991 if (err < 0)
3992 goto unlock;
3993
3994 if (changed)
3995 err = new_settings(hdev, sk);
3996
3997 goto unlock;
3998 }
3999
4000 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4001 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4002 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4003 MGMT_STATUS_BUSY);
4004 goto unlock;
4005 }
4006
4007 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4008 if (!cmd) {
4009 err = -ENOMEM;
4010 goto unlock;
4011 }
4012
4013 hci_req_init(&req, hdev);
4014
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004015 if (val)
4016 enable_advertising(&req);
4017 else
4018 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004019
4020 err = hci_req_run(&req, set_advertising_complete);
4021 if (err < 0)
4022 mgmt_pending_remove(cmd);
4023
4024unlock:
4025 hci_dev_unlock(hdev);
4026 return err;
4027}
4028
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004029static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4030 void *data, u16 len)
4031{
4032 struct mgmt_cp_set_static_address *cp = data;
4033 int err;
4034
4035 BT_DBG("%s", hdev->name);
4036
Marcel Holtmann62af4442013-10-02 22:10:32 -07004037 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004038 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004039 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004040
4041 if (hdev_is_powered(hdev))
4042 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4043 MGMT_STATUS_REJECTED);
4044
4045 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4046 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4047 return cmd_status(sk, hdev->id,
4048 MGMT_OP_SET_STATIC_ADDRESS,
4049 MGMT_STATUS_INVALID_PARAMS);
4050
4051 /* Two most significant bits shall be set */
4052 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4053 return cmd_status(sk, hdev->id,
4054 MGMT_OP_SET_STATIC_ADDRESS,
4055 MGMT_STATUS_INVALID_PARAMS);
4056 }
4057
4058 hci_dev_lock(hdev);
4059
4060 bacpy(&hdev->static_addr, &cp->bdaddr);
4061
4062 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4063
4064 hci_dev_unlock(hdev);
4065
4066 return err;
4067}
4068
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004069static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4070 void *data, u16 len)
4071{
4072 struct mgmt_cp_set_scan_params *cp = data;
4073 __u16 interval, window;
4074 int err;
4075
4076 BT_DBG("%s", hdev->name);
4077
4078 if (!lmp_le_capable(hdev))
4079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4080 MGMT_STATUS_NOT_SUPPORTED);
4081
4082 interval = __le16_to_cpu(cp->interval);
4083
4084 if (interval < 0x0004 || interval > 0x4000)
4085 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4086 MGMT_STATUS_INVALID_PARAMS);
4087
4088 window = __le16_to_cpu(cp->window);
4089
4090 if (window < 0x0004 || window > 0x4000)
4091 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4092 MGMT_STATUS_INVALID_PARAMS);
4093
Marcel Holtmann899e1072013-10-14 09:55:32 -07004094 if (window > interval)
4095 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4096 MGMT_STATUS_INVALID_PARAMS);
4097
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004098 hci_dev_lock(hdev);
4099
4100 hdev->le_scan_interval = interval;
4101 hdev->le_scan_window = window;
4102
4103 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4104
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004105 /* If background scan is running, restart it so new parameters are
4106 * loaded.
4107 */
4108 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4109 hdev->discovery.state == DISCOVERY_STOPPED) {
4110 struct hci_request req;
4111
4112 hci_req_init(&req, hdev);
4113
4114 hci_req_add_le_scan_disable(&req);
4115 hci_req_add_le_passive_scan(&req);
4116
4117 hci_req_run(&req, NULL);
4118 }
4119
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004120 hci_dev_unlock(hdev);
4121
4122 return err;
4123}
4124
Johan Hedberg33e38b32013-03-15 17:07:05 -05004125static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4126{
4127 struct pending_cmd *cmd;
4128
4129 BT_DBG("status 0x%02x", status);
4130
4131 hci_dev_lock(hdev);
4132
4133 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4134 if (!cmd)
4135 goto unlock;
4136
4137 if (status) {
4138 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4139 mgmt_status(status));
4140 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004141 struct mgmt_mode *cp = cmd->param;
4142
4143 if (cp->val)
4144 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4145 else
4146 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4147
Johan Hedberg33e38b32013-03-15 17:07:05 -05004148 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4149 new_settings(hdev, cmd->sk);
4150 }
4151
4152 mgmt_pending_remove(cmd);
4153
4154unlock:
4155 hci_dev_unlock(hdev);
4156}
4157
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004158static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004159 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004160{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004161 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004162 struct pending_cmd *cmd;
4163 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004164 int err;
4165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004166 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004167
Johan Hedberg56f87902013-10-02 13:43:13 +03004168 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4169 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004170 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4171 MGMT_STATUS_NOT_SUPPORTED);
4172
Johan Hedberga7e80f22013-01-09 16:05:19 +02004173 if (cp->val != 0x00 && cp->val != 0x01)
4174 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4175 MGMT_STATUS_INVALID_PARAMS);
4176
Johan Hedberg5400c042012-02-21 16:40:33 +02004177 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004178 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004179 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004180
4181 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004182 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004183 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004184
4185 hci_dev_lock(hdev);
4186
Johan Hedberg05cbf292013-03-15 17:07:07 -05004187 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4188 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4189 MGMT_STATUS_BUSY);
4190 goto unlock;
4191 }
4192
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004193 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4194 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4195 hdev);
4196 goto unlock;
4197 }
4198
Johan Hedberg33e38b32013-03-15 17:07:05 -05004199 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4200 data, len);
4201 if (!cmd) {
4202 err = -ENOMEM;
4203 goto unlock;
4204 }
4205
4206 hci_req_init(&req, hdev);
4207
Johan Hedberg406d7802013-03-15 17:07:09 -05004208 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004209
4210 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004211 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004212 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004213 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004214 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004215 }
4216
Johan Hedberg33e38b32013-03-15 17:07:05 -05004217unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004218 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004219
Antti Julkuf6422ec2011-06-22 13:11:56 +03004220 return err;
4221}
4222
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004223static void set_bredr_scan(struct hci_request *req)
4224{
4225 struct hci_dev *hdev = req->hdev;
4226 u8 scan = 0;
4227
4228 /* Ensure that fast connectable is disabled. This function will
4229 * not do anything if the page scan parameters are already what
4230 * they should be.
4231 */
4232 write_fast_connectable(req, false);
4233
4234 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4235 scan |= SCAN_PAGE;
4236 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4237 scan |= SCAN_INQUIRY;
4238
4239 if (scan)
4240 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4241}
4242
Johan Hedberg0663ca22013-10-02 13:43:14 +03004243static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4244{
4245 struct pending_cmd *cmd;
4246
4247 BT_DBG("status 0x%02x", status);
4248
4249 hci_dev_lock(hdev);
4250
4251 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4252 if (!cmd)
4253 goto unlock;
4254
4255 if (status) {
4256 u8 mgmt_err = mgmt_status(status);
4257
4258 /* We need to restore the flag if related HCI commands
4259 * failed.
4260 */
4261 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4262
4263 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4264 } else {
4265 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4266 new_settings(hdev, cmd->sk);
4267 }
4268
4269 mgmt_pending_remove(cmd);
4270
4271unlock:
4272 hci_dev_unlock(hdev);
4273}
4274
4275static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4276{
4277 struct mgmt_mode *cp = data;
4278 struct pending_cmd *cmd;
4279 struct hci_request req;
4280 int err;
4281
4282 BT_DBG("request for %s", hdev->name);
4283
4284 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4285 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4286 MGMT_STATUS_NOT_SUPPORTED);
4287
4288 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4289 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4290 MGMT_STATUS_REJECTED);
4291
4292 if (cp->val != 0x00 && cp->val != 0x01)
4293 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4294 MGMT_STATUS_INVALID_PARAMS);
4295
4296 hci_dev_lock(hdev);
4297
4298 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4299 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4300 goto unlock;
4301 }
4302
4303 if (!hdev_is_powered(hdev)) {
4304 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004305 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4306 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4307 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4308 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4309 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4310 }
4311
4312 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4313
4314 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4315 if (err < 0)
4316 goto unlock;
4317
4318 err = new_settings(hdev, sk);
4319 goto unlock;
4320 }
4321
4322 /* Reject disabling when powered on */
4323 if (!cp->val) {
4324 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4325 MGMT_STATUS_REJECTED);
4326 goto unlock;
4327 }
4328
4329 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4330 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4331 MGMT_STATUS_BUSY);
4332 goto unlock;
4333 }
4334
4335 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4336 if (!cmd) {
4337 err = -ENOMEM;
4338 goto unlock;
4339 }
4340
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004341 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004342 * generates the correct flags.
4343 */
4344 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4345
4346 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004347
4348 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4349 set_bredr_scan(&req);
4350
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004351 /* Since only the advertising data flags will change, there
4352 * is no need to update the scan response data.
4353 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004354 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004355
Johan Hedberg0663ca22013-10-02 13:43:14 +03004356 err = hci_req_run(&req, set_bredr_complete);
4357 if (err < 0)
4358 mgmt_pending_remove(cmd);
4359
4360unlock:
4361 hci_dev_unlock(hdev);
4362 return err;
4363}
4364
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004365static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4366 void *data, u16 len)
4367{
4368 struct mgmt_mode *cp = data;
4369 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004370 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004371 int err;
4372
4373 BT_DBG("request for %s", hdev->name);
4374
4375 status = mgmt_bredr_support(hdev);
4376 if (status)
4377 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4378 status);
4379
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004380 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004381 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004382 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4383 MGMT_STATUS_NOT_SUPPORTED);
4384
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004385 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004386 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4387 MGMT_STATUS_INVALID_PARAMS);
4388
4389 hci_dev_lock(hdev);
4390
4391 if (!hdev_is_powered(hdev)) {
4392 bool changed;
4393
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004394 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004395 changed = !test_and_set_bit(HCI_SC_ENABLED,
4396 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004397 if (cp->val == 0x02)
4398 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4399 else
4400 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4401 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004402 changed = test_and_clear_bit(HCI_SC_ENABLED,
4403 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004404 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4405 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004406
4407 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4408 if (err < 0)
4409 goto failed;
4410
4411 if (changed)
4412 err = new_settings(hdev, sk);
4413
4414 goto failed;
4415 }
4416
4417 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4418 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4419 MGMT_STATUS_BUSY);
4420 goto failed;
4421 }
4422
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004423 val = !!cp->val;
4424
4425 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4426 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004427 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4428 goto failed;
4429 }
4430
4431 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4432 if (!cmd) {
4433 err = -ENOMEM;
4434 goto failed;
4435 }
4436
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004437 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004438 if (err < 0) {
4439 mgmt_pending_remove(cmd);
4440 goto failed;
4441 }
4442
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004443 if (cp->val == 0x02)
4444 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4445 else
4446 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4447
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004448failed:
4449 hci_dev_unlock(hdev);
4450 return err;
4451}
4452
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004453static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4454 void *data, u16 len)
4455{
4456 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004457 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004458 int err;
4459
4460 BT_DBG("request for %s", hdev->name);
4461
Johan Hedbergb97109792014-06-24 14:00:28 +03004462 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004463 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4464 MGMT_STATUS_INVALID_PARAMS);
4465
4466 hci_dev_lock(hdev);
4467
4468 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004469 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4470 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004471 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004472 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4473 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004474
Johan Hedbergb97109792014-06-24 14:00:28 +03004475 if (cp->val == 0x02)
4476 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4477 &hdev->dev_flags);
4478 else
4479 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4480 &hdev->dev_flags);
4481
4482 if (hdev_is_powered(hdev) && use_changed &&
4483 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4484 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4485 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4486 sizeof(mode), &mode);
4487 }
4488
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004489 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4490 if (err < 0)
4491 goto unlock;
4492
4493 if (changed)
4494 err = new_settings(hdev, sk);
4495
4496unlock:
4497 hci_dev_unlock(hdev);
4498 return err;
4499}
4500
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004501static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4502 u16 len)
4503{
4504 struct mgmt_cp_set_privacy *cp = cp_data;
4505 bool changed;
4506 int err;
4507
4508 BT_DBG("request for %s", hdev->name);
4509
4510 if (!lmp_le_capable(hdev))
4511 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4512 MGMT_STATUS_NOT_SUPPORTED);
4513
4514 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4515 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4516 MGMT_STATUS_INVALID_PARAMS);
4517
4518 if (hdev_is_powered(hdev))
4519 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4520 MGMT_STATUS_REJECTED);
4521
4522 hci_dev_lock(hdev);
4523
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004524 /* If user space supports this command it is also expected to
4525 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4526 */
4527 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4528
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004529 if (cp->privacy) {
4530 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4531 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4532 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4533 } else {
4534 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4535 memset(hdev->irk, 0, sizeof(hdev->irk));
4536 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4537 }
4538
4539 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4540 if (err < 0)
4541 goto unlock;
4542
4543 if (changed)
4544 err = new_settings(hdev, sk);
4545
4546unlock:
4547 hci_dev_unlock(hdev);
4548 return err;
4549}
4550
Johan Hedberg41edf162014-02-18 10:19:35 +02004551static bool irk_is_valid(struct mgmt_irk_info *irk)
4552{
4553 switch (irk->addr.type) {
4554 case BDADDR_LE_PUBLIC:
4555 return true;
4556
4557 case BDADDR_LE_RANDOM:
4558 /* Two most significant bits shall be set */
4559 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4560 return false;
4561 return true;
4562 }
4563
4564 return false;
4565}
4566
4567static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4568 u16 len)
4569{
4570 struct mgmt_cp_load_irks *cp = cp_data;
4571 u16 irk_count, expected_len;
4572 int i, err;
4573
4574 BT_DBG("request for %s", hdev->name);
4575
4576 if (!lmp_le_capable(hdev))
4577 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4578 MGMT_STATUS_NOT_SUPPORTED);
4579
4580 irk_count = __le16_to_cpu(cp->irk_count);
4581
4582 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4583 if (expected_len != len) {
4584 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004585 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004586 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4587 MGMT_STATUS_INVALID_PARAMS);
4588 }
4589
4590 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4591
4592 for (i = 0; i < irk_count; i++) {
4593 struct mgmt_irk_info *key = &cp->irks[i];
4594
4595 if (!irk_is_valid(key))
4596 return cmd_status(sk, hdev->id,
4597 MGMT_OP_LOAD_IRKS,
4598 MGMT_STATUS_INVALID_PARAMS);
4599 }
4600
4601 hci_dev_lock(hdev);
4602
4603 hci_smp_irks_clear(hdev);
4604
4605 for (i = 0; i < irk_count; i++) {
4606 struct mgmt_irk_info *irk = &cp->irks[i];
4607 u8 addr_type;
4608
4609 if (irk->addr.type == BDADDR_LE_PUBLIC)
4610 addr_type = ADDR_LE_DEV_PUBLIC;
4611 else
4612 addr_type = ADDR_LE_DEV_RANDOM;
4613
4614 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4615 BDADDR_ANY);
4616 }
4617
4618 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4619
4620 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4621
4622 hci_dev_unlock(hdev);
4623
4624 return err;
4625}
4626
Johan Hedberg3f706b72013-01-20 14:27:16 +02004627static bool ltk_is_valid(struct mgmt_ltk_info *key)
4628{
4629 if (key->master != 0x00 && key->master != 0x01)
4630 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004631
4632 switch (key->addr.type) {
4633 case BDADDR_LE_PUBLIC:
4634 return true;
4635
4636 case BDADDR_LE_RANDOM:
4637 /* Two most significant bits shall be set */
4638 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4639 return false;
4640 return true;
4641 }
4642
4643 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004644}
4645
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004646static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004647 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004648{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004649 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4650 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004651 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004652
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004653 BT_DBG("request for %s", hdev->name);
4654
4655 if (!lmp_le_capable(hdev))
4656 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4657 MGMT_STATUS_NOT_SUPPORTED);
4658
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004659 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004660
4661 expected_len = sizeof(*cp) + key_count *
4662 sizeof(struct mgmt_ltk_info);
4663 if (expected_len != len) {
4664 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004665 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004666 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004667 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004668 }
4669
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004670 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004671
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004672 for (i = 0; i < key_count; i++) {
4673 struct mgmt_ltk_info *key = &cp->keys[i];
4674
Johan Hedberg3f706b72013-01-20 14:27:16 +02004675 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004676 return cmd_status(sk, hdev->id,
4677 MGMT_OP_LOAD_LONG_TERM_KEYS,
4678 MGMT_STATUS_INVALID_PARAMS);
4679 }
4680
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004681 hci_dev_lock(hdev);
4682
4683 hci_smp_ltks_clear(hdev);
4684
4685 for (i = 0; i < key_count; i++) {
4686 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004687 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004688
4689 if (key->addr.type == BDADDR_LE_PUBLIC)
4690 addr_type = ADDR_LE_DEV_PUBLIC;
4691 else
4692 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004693
4694 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004695 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004696 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004697 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004698
Johan Hedberg61b43352014-05-29 19:36:53 +03004699 switch (key->type) {
4700 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004701 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004702 break;
4703 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004704 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004705 break;
4706 default:
4707 continue;
4708 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004709
Johan Hedberg35d70272014-02-19 14:57:47 +02004710 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004711 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004712 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004713 }
4714
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004715 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4716 NULL, 0);
4717
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004718 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004719
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004720 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004721}
4722
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004723struct cmd_conn_lookup {
4724 struct hci_conn *conn;
4725 bool valid_tx_power;
4726 u8 mgmt_status;
4727};
4728
4729static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4730{
4731 struct cmd_conn_lookup *match = data;
4732 struct mgmt_cp_get_conn_info *cp;
4733 struct mgmt_rp_get_conn_info rp;
4734 struct hci_conn *conn = cmd->user_data;
4735
4736 if (conn != match->conn)
4737 return;
4738
4739 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4740
4741 memset(&rp, 0, sizeof(rp));
4742 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4743 rp.addr.type = cp->addr.type;
4744
4745 if (!match->mgmt_status) {
4746 rp.rssi = conn->rssi;
4747
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004748 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004749 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004750 rp.max_tx_power = conn->max_tx_power;
4751 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004752 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004753 rp.max_tx_power = HCI_TX_POWER_INVALID;
4754 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004755 }
4756
4757 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4758 match->mgmt_status, &rp, sizeof(rp));
4759
4760 hci_conn_drop(conn);
4761
4762 mgmt_pending_remove(cmd);
4763}
4764
4765static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4766{
4767 struct hci_cp_read_rssi *cp;
4768 struct hci_conn *conn;
4769 struct cmd_conn_lookup match;
4770 u16 handle;
4771
4772 BT_DBG("status 0x%02x", status);
4773
4774 hci_dev_lock(hdev);
4775
4776 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004777 * otherwise we assume it's not valid. At the moment we assume that
4778 * either both or none of current and max values are valid to keep code
4779 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004780 */
4781 match.valid_tx_power = !status;
4782
4783 /* Commands sent in request are either Read RSSI or Read Transmit Power
4784 * Level so we check which one was last sent to retrieve connection
4785 * handle. Both commands have handle as first parameter so it's safe to
4786 * cast data on the same command struct.
4787 *
4788 * First command sent is always Read RSSI and we fail only if it fails.
4789 * In other case we simply override error to indicate success as we
4790 * already remembered if TX power value is actually valid.
4791 */
4792 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4793 if (!cp) {
4794 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4795 status = 0;
4796 }
4797
4798 if (!cp) {
4799 BT_ERR("invalid sent_cmd in response");
4800 goto unlock;
4801 }
4802
4803 handle = __le16_to_cpu(cp->handle);
4804 conn = hci_conn_hash_lookup_handle(hdev, handle);
4805 if (!conn) {
4806 BT_ERR("unknown handle (%d) in response", handle);
4807 goto unlock;
4808 }
4809
4810 match.conn = conn;
4811 match.mgmt_status = mgmt_status(status);
4812
4813 /* Cache refresh is complete, now reply for mgmt request for given
4814 * connection only.
4815 */
4816 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4817 get_conn_info_complete, &match);
4818
4819unlock:
4820 hci_dev_unlock(hdev);
4821}
4822
4823static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4824 u16 len)
4825{
4826 struct mgmt_cp_get_conn_info *cp = data;
4827 struct mgmt_rp_get_conn_info rp;
4828 struct hci_conn *conn;
4829 unsigned long conn_info_age;
4830 int err = 0;
4831
4832 BT_DBG("%s", hdev->name);
4833
4834 memset(&rp, 0, sizeof(rp));
4835 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4836 rp.addr.type = cp->addr.type;
4837
4838 if (!bdaddr_type_is_valid(cp->addr.type))
4839 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4840 MGMT_STATUS_INVALID_PARAMS,
4841 &rp, sizeof(rp));
4842
4843 hci_dev_lock(hdev);
4844
4845 if (!hdev_is_powered(hdev)) {
4846 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4847 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4848 goto unlock;
4849 }
4850
4851 if (cp->addr.type == BDADDR_BREDR)
4852 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4853 &cp->addr.bdaddr);
4854 else
4855 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4856
4857 if (!conn || conn->state != BT_CONNECTED) {
4858 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4859 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4860 goto unlock;
4861 }
4862
4863 /* To avoid client trying to guess when to poll again for information we
4864 * calculate conn info age as random value between min/max set in hdev.
4865 */
4866 conn_info_age = hdev->conn_info_min_age +
4867 prandom_u32_max(hdev->conn_info_max_age -
4868 hdev->conn_info_min_age);
4869
4870 /* Query controller to refresh cached values if they are too old or were
4871 * never read.
4872 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004873 if (time_after(jiffies, conn->conn_info_timestamp +
4874 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004875 !conn->conn_info_timestamp) {
4876 struct hci_request req;
4877 struct hci_cp_read_tx_power req_txp_cp;
4878 struct hci_cp_read_rssi req_rssi_cp;
4879 struct pending_cmd *cmd;
4880
4881 hci_req_init(&req, hdev);
4882 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4883 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4884 &req_rssi_cp);
4885
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004886 /* For LE links TX power does not change thus we don't need to
4887 * query for it once value is known.
4888 */
4889 if (!bdaddr_type_is_le(cp->addr.type) ||
4890 conn->tx_power == HCI_TX_POWER_INVALID) {
4891 req_txp_cp.handle = cpu_to_le16(conn->handle);
4892 req_txp_cp.type = 0x00;
4893 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4894 sizeof(req_txp_cp), &req_txp_cp);
4895 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004896
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004897 /* Max TX power needs to be read only once per connection */
4898 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4899 req_txp_cp.handle = cpu_to_le16(conn->handle);
4900 req_txp_cp.type = 0x01;
4901 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4902 sizeof(req_txp_cp), &req_txp_cp);
4903 }
4904
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004905 err = hci_req_run(&req, conn_info_refresh_complete);
4906 if (err < 0)
4907 goto unlock;
4908
4909 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4910 data, len);
4911 if (!cmd) {
4912 err = -ENOMEM;
4913 goto unlock;
4914 }
4915
4916 hci_conn_hold(conn);
4917 cmd->user_data = conn;
4918
4919 conn->conn_info_timestamp = jiffies;
4920 } else {
4921 /* Cache is valid, just reply with values cached in hci_conn */
4922 rp.rssi = conn->rssi;
4923 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004924 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004925
4926 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4927 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4928 }
4929
4930unlock:
4931 hci_dev_unlock(hdev);
4932 return err;
4933}
4934
Johan Hedberg95868422014-06-28 17:54:07 +03004935static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4936{
4937 struct mgmt_cp_get_clock_info *cp;
4938 struct mgmt_rp_get_clock_info rp;
4939 struct hci_cp_read_clock *hci_cp;
4940 struct pending_cmd *cmd;
4941 struct hci_conn *conn;
4942
4943 BT_DBG("%s status %u", hdev->name, status);
4944
4945 hci_dev_lock(hdev);
4946
4947 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4948 if (!hci_cp)
4949 goto unlock;
4950
4951 if (hci_cp->which) {
4952 u16 handle = __le16_to_cpu(hci_cp->handle);
4953 conn = hci_conn_hash_lookup_handle(hdev, handle);
4954 } else {
4955 conn = NULL;
4956 }
4957
4958 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4959 if (!cmd)
4960 goto unlock;
4961
4962 cp = cmd->param;
4963
4964 memset(&rp, 0, sizeof(rp));
4965 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4966
4967 if (status)
4968 goto send_rsp;
4969
4970 rp.local_clock = cpu_to_le32(hdev->clock);
4971
4972 if (conn) {
4973 rp.piconet_clock = cpu_to_le32(conn->clock);
4974 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4975 }
4976
4977send_rsp:
4978 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
4979 &rp, sizeof(rp));
4980 mgmt_pending_remove(cmd);
4981 if (conn)
4982 hci_conn_drop(conn);
4983
4984unlock:
4985 hci_dev_unlock(hdev);
4986}
4987
4988static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
4989 u16 len)
4990{
4991 struct mgmt_cp_get_clock_info *cp = data;
4992 struct mgmt_rp_get_clock_info rp;
4993 struct hci_cp_read_clock hci_cp;
4994 struct pending_cmd *cmd;
4995 struct hci_request req;
4996 struct hci_conn *conn;
4997 int err;
4998
4999 BT_DBG("%s", hdev->name);
5000
5001 memset(&rp, 0, sizeof(rp));
5002 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5003 rp.addr.type = cp->addr.type;
5004
5005 if (cp->addr.type != BDADDR_BREDR)
5006 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5007 MGMT_STATUS_INVALID_PARAMS,
5008 &rp, sizeof(rp));
5009
5010 hci_dev_lock(hdev);
5011
5012 if (!hdev_is_powered(hdev)) {
5013 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5014 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5015 goto unlock;
5016 }
5017
5018 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5019 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5020 &cp->addr.bdaddr);
5021 if (!conn || conn->state != BT_CONNECTED) {
5022 err = cmd_complete(sk, hdev->id,
5023 MGMT_OP_GET_CLOCK_INFO,
5024 MGMT_STATUS_NOT_CONNECTED,
5025 &rp, sizeof(rp));
5026 goto unlock;
5027 }
5028 } else {
5029 conn = NULL;
5030 }
5031
5032 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5033 if (!cmd) {
5034 err = -ENOMEM;
5035 goto unlock;
5036 }
5037
5038 hci_req_init(&req, hdev);
5039
5040 memset(&hci_cp, 0, sizeof(hci_cp));
5041 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5042
5043 if (conn) {
5044 hci_conn_hold(conn);
5045 cmd->user_data = conn;
5046
5047 hci_cp.handle = cpu_to_le16(conn->handle);
5048 hci_cp.which = 0x01; /* Piconet clock */
5049 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5050 }
5051
5052 err = hci_req_run(&req, get_clock_info_complete);
5053 if (err < 0)
5054 mgmt_pending_remove(cmd);
5055
5056unlock:
5057 hci_dev_unlock(hdev);
5058 return err;
5059}
5060
Marcel Holtmann8afef092014-06-29 22:28:34 +02005061static void device_added(struct sock *sk, struct hci_dev *hdev,
5062 bdaddr_t *bdaddr, u8 type, u8 action)
5063{
5064 struct mgmt_ev_device_added ev;
5065
5066 bacpy(&ev.addr.bdaddr, bdaddr);
5067 ev.addr.type = type;
5068 ev.action = action;
5069
5070 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5071}
5072
Marcel Holtmann2faade52014-06-29 19:44:03 +02005073static int add_device(struct sock *sk, struct hci_dev *hdev,
5074 void *data, u16 len)
5075{
5076 struct mgmt_cp_add_device *cp = data;
5077 u8 auto_conn, addr_type;
5078 int err;
5079
5080 BT_DBG("%s", hdev->name);
5081
5082 if (!bdaddr_type_is_le(cp->addr.type) ||
5083 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5084 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5085 MGMT_STATUS_INVALID_PARAMS,
5086 &cp->addr, sizeof(cp->addr));
5087
5088 if (cp->action != 0x00 && cp->action != 0x01)
5089 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5090 MGMT_STATUS_INVALID_PARAMS,
5091 &cp->addr, sizeof(cp->addr));
5092
5093 hci_dev_lock(hdev);
5094
5095 if (cp->addr.type == BDADDR_LE_PUBLIC)
5096 addr_type = ADDR_LE_DEV_PUBLIC;
5097 else
5098 addr_type = ADDR_LE_DEV_RANDOM;
5099
5100 if (cp->action)
5101 auto_conn = HCI_AUTO_CONN_ALWAYS;
5102 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005103 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005104
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005105 /* If the connection parameters don't exist for this device,
5106 * they will be created and configured with defaults.
5107 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005108 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5109 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005110 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5111 MGMT_STATUS_FAILED,
5112 &cp->addr, sizeof(cp->addr));
5113 goto unlock;
5114 }
5115
Marcel Holtmann8afef092014-06-29 22:28:34 +02005116 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5117
Marcel Holtmann2faade52014-06-29 19:44:03 +02005118 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5119 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5120
5121unlock:
5122 hci_dev_unlock(hdev);
5123 return err;
5124}
5125
Marcel Holtmann8afef092014-06-29 22:28:34 +02005126static void device_removed(struct sock *sk, struct hci_dev *hdev,
5127 bdaddr_t *bdaddr, u8 type)
5128{
5129 struct mgmt_ev_device_removed ev;
5130
5131 bacpy(&ev.addr.bdaddr, bdaddr);
5132 ev.addr.type = type;
5133
5134 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5135}
5136
Marcel Holtmann2faade52014-06-29 19:44:03 +02005137static int remove_device(struct sock *sk, struct hci_dev *hdev,
5138 void *data, u16 len)
5139{
5140 struct mgmt_cp_remove_device *cp = data;
5141 int err;
5142
5143 BT_DBG("%s", hdev->name);
5144
5145 hci_dev_lock(hdev);
5146
5147 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005148 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005149 u8 addr_type;
5150
5151 if (!bdaddr_type_is_le(cp->addr.type)) {
5152 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5153 MGMT_STATUS_INVALID_PARAMS,
5154 &cp->addr, sizeof(cp->addr));
5155 goto unlock;
5156 }
5157
5158 if (cp->addr.type == BDADDR_LE_PUBLIC)
5159 addr_type = ADDR_LE_DEV_PUBLIC;
5160 else
5161 addr_type = ADDR_LE_DEV_RANDOM;
5162
Johan Hedbergc71593d2014-07-02 17:37:28 +03005163 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5164 addr_type);
5165 if (!params) {
5166 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5167 MGMT_STATUS_INVALID_PARAMS,
5168 &cp->addr, sizeof(cp->addr));
5169 goto unlock;
5170 }
5171
5172 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5173 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5174 MGMT_STATUS_INVALID_PARAMS,
5175 &cp->addr, sizeof(cp->addr));
5176 goto unlock;
5177 }
5178
5179 hci_pend_le_conn_del(hdev, &cp->addr.bdaddr, addr_type);
5180 list_del(&params->list);
5181 kfree(params);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005182
5183 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005184 } else {
5185 if (cp->addr.type) {
5186 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5187 MGMT_STATUS_INVALID_PARAMS,
5188 &cp->addr, sizeof(cp->addr));
5189 goto unlock;
5190 }
5191
Johan Hedbergc71593d2014-07-02 17:37:28 +03005192 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005193 }
5194
5195 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5196 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5197
5198unlock:
5199 hci_dev_unlock(hdev);
5200 return err;
5201}
5202
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005203static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5204 u16 len)
5205{
5206 struct mgmt_cp_load_conn_param *cp = data;
5207 u16 param_count, expected_len;
5208 int i;
5209
5210 if (!lmp_le_capable(hdev))
5211 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5212 MGMT_STATUS_NOT_SUPPORTED);
5213
5214 param_count = __le16_to_cpu(cp->param_count);
5215
5216 expected_len = sizeof(*cp) + param_count *
5217 sizeof(struct mgmt_conn_param);
5218 if (expected_len != len) {
5219 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5220 expected_len, len);
5221 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5222 MGMT_STATUS_INVALID_PARAMS);
5223 }
5224
5225 BT_DBG("%s param_count %u", hdev->name, param_count);
5226
5227 hci_dev_lock(hdev);
5228
5229 hci_conn_params_clear_disabled(hdev);
5230
5231 for (i = 0; i < param_count; i++) {
5232 struct mgmt_conn_param *param = &cp->params[i];
5233 struct hci_conn_params *hci_param;
5234 u16 min, max, latency, timeout;
5235 u8 addr_type;
5236
5237 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5238 param->addr.type);
5239
5240 if (param->addr.type == BDADDR_LE_PUBLIC) {
5241 addr_type = ADDR_LE_DEV_PUBLIC;
5242 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5243 addr_type = ADDR_LE_DEV_RANDOM;
5244 } else {
5245 BT_ERR("Ignoring invalid connection parameters");
5246 continue;
5247 }
5248
5249 min = le16_to_cpu(param->min_interval);
5250 max = le16_to_cpu(param->max_interval);
5251 latency = le16_to_cpu(param->latency);
5252 timeout = le16_to_cpu(param->timeout);
5253
5254 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5255 min, max, latency, timeout);
5256
5257 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5258 BT_ERR("Ignoring invalid connection parameters");
5259 continue;
5260 }
5261
5262 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5263 addr_type);
5264 if (!hci_param) {
5265 BT_ERR("Failed to add connection parameters");
5266 continue;
5267 }
5268
5269 hci_param->conn_min_interval = min;
5270 hci_param->conn_max_interval = max;
5271 hci_param->conn_latency = latency;
5272 hci_param->supervision_timeout = timeout;
5273 }
5274
5275 hci_dev_unlock(hdev);
5276
5277 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5278}
5279
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005280static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005281 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5282 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005283 bool var_len;
5284 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005285} mgmt_handlers[] = {
5286 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005287 { read_version, false, MGMT_READ_VERSION_SIZE },
5288 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5289 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5290 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5291 { set_powered, false, MGMT_SETTING_SIZE },
5292 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5293 { set_connectable, false, MGMT_SETTING_SIZE },
5294 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5295 { set_pairable, false, MGMT_SETTING_SIZE },
5296 { set_link_security, false, MGMT_SETTING_SIZE },
5297 { set_ssp, false, MGMT_SETTING_SIZE },
5298 { set_hs, false, MGMT_SETTING_SIZE },
5299 { set_le, false, MGMT_SETTING_SIZE },
5300 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5301 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5302 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5303 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5304 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5305 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5306 { disconnect, false, MGMT_DISCONNECT_SIZE },
5307 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5308 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5309 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5310 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5311 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5312 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5313 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5314 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5315 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5316 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5317 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5318 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005319 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005320 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5321 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5322 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5323 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5324 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5325 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005326 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005327 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005328 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005329 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005330 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005331 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005332 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005333 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005334 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005335 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005336 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005337 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5338 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005339 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5340 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005341};
5342
Johan Hedberg03811012010-12-08 00:21:06 +02005343int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5344{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005345 void *buf;
5346 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005347 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005348 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005349 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005350 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005351 int err;
5352
5353 BT_DBG("got %zu bytes", msglen);
5354
5355 if (msglen < sizeof(*hdr))
5356 return -EINVAL;
5357
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005358 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005359 if (!buf)
5360 return -ENOMEM;
5361
5362 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5363 err = -EFAULT;
5364 goto done;
5365 }
5366
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005367 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005368 opcode = __le16_to_cpu(hdr->opcode);
5369 index = __le16_to_cpu(hdr->index);
5370 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005371
5372 if (len != msglen - sizeof(*hdr)) {
5373 err = -EINVAL;
5374 goto done;
5375 }
5376
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005377 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005378 hdev = hci_dev_get(index);
5379 if (!hdev) {
5380 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005381 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005382 goto done;
5383 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005384
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005385 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005386 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5387 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005388 err = cmd_status(sk, index, opcode,
5389 MGMT_STATUS_INVALID_INDEX);
5390 goto done;
5391 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005392 }
5393
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005394 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005395 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005396 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005397 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005398 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005399 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005400 }
5401
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005402 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5403 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5404 err = cmd_status(sk, index, opcode,
5405 MGMT_STATUS_INVALID_INDEX);
5406 goto done;
5407 }
5408
5409 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5410 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005411 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005412 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005413 goto done;
5414 }
5415
Johan Hedbergbe22b542012-03-01 22:24:41 +02005416 handler = &mgmt_handlers[opcode];
5417
5418 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005419 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005420 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005421 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005422 goto done;
5423 }
5424
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005425 if (hdev)
5426 mgmt_init_hdev(sk, hdev);
5427
5428 cp = buf + sizeof(*hdr);
5429
Johan Hedbergbe22b542012-03-01 22:24:41 +02005430 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005431 if (err < 0)
5432 goto done;
5433
Johan Hedberg03811012010-12-08 00:21:06 +02005434 err = msglen;
5435
5436done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005437 if (hdev)
5438 hci_dev_put(hdev);
5439
Johan Hedberg03811012010-12-08 00:21:06 +02005440 kfree(buf);
5441 return err;
5442}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005443
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005444void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005445{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005446 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005447 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005448
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005449 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5450 return;
5451
5452 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5453 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5454 else
5455 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005456}
5457
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005458void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005459{
Johan Hedberg5f159032012-03-02 03:13:19 +02005460 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005461
Marcel Holtmann1514b892013-10-06 08:25:01 -07005462 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005463 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005464
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005465 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5466 return;
5467
Johan Hedberg744cf192011-11-08 20:40:14 +02005468 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005469
Marcel Holtmannedd38962014-07-02 21:30:55 +02005470 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5471 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5472 else
5473 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005474}
5475
Andre Guedes6046dc32014-02-26 20:21:51 -03005476/* This function requires the caller holds hdev->lock */
5477static void restart_le_auto_conns(struct hci_dev *hdev)
5478{
5479 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005480 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005481
5482 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005483 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005484 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005485 added = true;
5486 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005487 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005488
5489 /* Calling hci_pend_le_conn_add will actually already trigger
5490 * background scanning when needed. So no need to trigger it
5491 * just another time.
5492 *
5493 * This check is here to avoid an unneeded restart of the
5494 * passive scanning. Since this is during the controller
5495 * power up phase the duplicate filtering is not an issue.
5496 */
5497 if (added)
5498 return;
5499
5500 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005501}
5502
Johan Hedberg229ab392013-03-15 17:06:53 -05005503static void powered_complete(struct hci_dev *hdev, u8 status)
5504{
5505 struct cmd_lookup match = { NULL, hdev };
5506
5507 BT_DBG("status 0x%02x", status);
5508
5509 hci_dev_lock(hdev);
5510
Andre Guedes6046dc32014-02-26 20:21:51 -03005511 restart_le_auto_conns(hdev);
5512
Johan Hedberg229ab392013-03-15 17:06:53 -05005513 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5514
5515 new_settings(hdev, match.sk);
5516
5517 hci_dev_unlock(hdev);
5518
5519 if (match.sk)
5520 sock_put(match.sk);
5521}
5522
Johan Hedberg70da6242013-03-15 17:06:51 -05005523static int powered_update_hci(struct hci_dev *hdev)
5524{
Johan Hedberg890ea892013-03-15 17:06:52 -05005525 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005526 u8 link_sec;
5527
Johan Hedberg890ea892013-03-15 17:06:52 -05005528 hci_req_init(&req, hdev);
5529
Johan Hedberg70da6242013-03-15 17:06:51 -05005530 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5531 !lmp_host_ssp_capable(hdev)) {
5532 u8 ssp = 1;
5533
Johan Hedberg890ea892013-03-15 17:06:52 -05005534 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005535 }
5536
Johan Hedbergc73eee92013-04-19 18:35:21 +03005537 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5538 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005539 struct hci_cp_write_le_host_supported cp;
5540
5541 cp.le = 1;
5542 cp.simul = lmp_le_br_capable(hdev);
5543
5544 /* Check first if we already have the right
5545 * host state (host features set)
5546 */
5547 if (cp.le != lmp_host_le_capable(hdev) ||
5548 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005549 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5550 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005551 }
5552
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005553 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005554 /* Make sure the controller has a good default for
5555 * advertising data. This also applies to the case
5556 * where BR/EDR was toggled during the AUTO_OFF phase.
5557 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005558 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005559 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005560 update_scan_rsp_data(&req);
5561 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005562
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005563 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5564 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005565 }
5566
Johan Hedberg70da6242013-03-15 17:06:51 -05005567 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5568 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005569 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5570 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005571
5572 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005573 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5574 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005575 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005576 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005577 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005578 }
5579
Johan Hedberg229ab392013-03-15 17:06:53 -05005580 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005581}
5582
Johan Hedberg744cf192011-11-08 20:40:14 +02005583int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005584{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005585 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005586 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5587 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005588 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005589
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005590 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5591 return 0;
5592
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005593 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005594 if (powered_update_hci(hdev) == 0)
5595 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005596
Johan Hedberg229ab392013-03-15 17:06:53 -05005597 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5598 &match);
5599 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005600 }
5601
Johan Hedberg229ab392013-03-15 17:06:53 -05005602 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5603 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5604
5605 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5606 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5607 zero_cod, sizeof(zero_cod), NULL);
5608
5609new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005610 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005611
5612 if (match.sk)
5613 sock_put(match.sk);
5614
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005615 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005616}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005617
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005618void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005619{
5620 struct pending_cmd *cmd;
5621 u8 status;
5622
5623 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5624 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005625 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005626
5627 if (err == -ERFKILL)
5628 status = MGMT_STATUS_RFKILLED;
5629 else
5630 status = MGMT_STATUS_FAILED;
5631
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005632 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005633
5634 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005635}
5636
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005637void mgmt_discoverable_timeout(struct hci_dev *hdev)
5638{
5639 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005640
5641 hci_dev_lock(hdev);
5642
5643 /* When discoverable timeout triggers, then just make sure
5644 * the limited discoverable flag is cleared. Even in the case
5645 * of a timeout triggered from general discoverable, it is
5646 * safe to unconditionally clear the flag.
5647 */
5648 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005649 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005650
5651 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005652 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5653 u8 scan = SCAN_PAGE;
5654 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5655 sizeof(scan), &scan);
5656 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005657 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005658 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005659 hci_req_run(&req, NULL);
5660
5661 hdev->discov_timeout = 0;
5662
Johan Hedberg9a43e252013-10-20 19:00:07 +03005663 new_settings(hdev, NULL);
5664
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005665 hci_dev_unlock(hdev);
5666}
5667
Marcel Holtmann86a75642013-10-15 06:33:54 -07005668void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005669{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005670 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005671
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005672 /* Nothing needed here if there's a pending command since that
5673 * commands request completion callback takes care of everything
5674 * necessary.
5675 */
5676 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005677 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005678
Johan Hedbergbd107992014-02-24 14:52:19 +02005679 /* Powering off may clear the scan mode - don't let that interfere */
5680 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5681 return;
5682
Johan Hedberg9a43e252013-10-20 19:00:07 +03005683 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005684 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005685 } else {
5686 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005687 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005688 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005689
Johan Hedberg9a43e252013-10-20 19:00:07 +03005690 if (changed) {
5691 struct hci_request req;
5692
5693 /* In case this change in discoverable was triggered by
5694 * a disabling of connectable there could be a need to
5695 * update the advertising flags.
5696 */
5697 hci_req_init(&req, hdev);
5698 update_adv_data(&req);
5699 hci_req_run(&req, NULL);
5700
Marcel Holtmann86a75642013-10-15 06:33:54 -07005701 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005702 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005703}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005704
Marcel Holtmanna3309162013-10-15 06:33:55 -07005705void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005706{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005707 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005708
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005709 /* Nothing needed here if there's a pending command since that
5710 * commands request completion callback takes care of everything
5711 * necessary.
5712 */
5713 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005714 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005715
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005716 /* Powering off may clear the scan mode - don't let that interfere */
5717 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5718 return;
5719
Marcel Holtmanna3309162013-10-15 06:33:55 -07005720 if (connectable)
5721 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5722 else
5723 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005724
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005725 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005726 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005727}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005728
Johan Hedberg778b2352014-02-24 14:52:17 +02005729void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5730{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005731 /* Powering off may stop advertising - don't let that interfere */
5732 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5733 return;
5734
Johan Hedberg778b2352014-02-24 14:52:17 +02005735 if (advertising)
5736 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5737 else
5738 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5739}
5740
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005741void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005742{
Johan Hedbergca69b792011-11-11 18:10:00 +02005743 u8 mgmt_err = mgmt_status(status);
5744
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005745 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005746 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005747 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005748
5749 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005750 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005751 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005752}
5753
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005754void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5755 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005756{
Johan Hedberg86742e12011-11-07 23:13:38 +02005757 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005758
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005759 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005760
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005761 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005762 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005763 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005764 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005765 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005766 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005767
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005768 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005769}
Johan Hedbergf7520542011-01-20 12:34:39 +02005770
Johan Hedbergd7b25452014-05-23 13:19:53 +03005771static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5772{
5773 if (ltk->authenticated)
5774 return MGMT_LTK_AUTHENTICATED;
5775
5776 return MGMT_LTK_UNAUTHENTICATED;
5777}
5778
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005779void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005780{
5781 struct mgmt_ev_new_long_term_key ev;
5782
5783 memset(&ev, 0, sizeof(ev));
5784
Marcel Holtmann5192d302014-02-19 17:11:58 -08005785 /* Devices using resolvable or non-resolvable random addresses
5786 * without providing an indentity resolving key don't require
5787 * to store long term keys. Their addresses will change the
5788 * next time around.
5789 *
5790 * Only when a remote device provides an identity address
5791 * make sure the long term key is stored. If the remote
5792 * identity is known, the long term keys are internally
5793 * mapped to the identity address. So allow static random
5794 * and public addresses here.
5795 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005796 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5797 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5798 ev.store_hint = 0x00;
5799 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005800 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005801
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005802 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005803 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005804 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005805 ev.key.enc_size = key->enc_size;
5806 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005807 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005808
Johan Hedberg2ceba532014-06-16 19:25:16 +03005809 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005810 ev.key.master = 1;
5811
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005812 memcpy(ev.key.val, key->val, sizeof(key->val));
5813
Marcel Holtmann083368f2013-10-15 14:26:29 -07005814 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005815}
5816
Johan Hedberg95fbac82014-02-19 15:18:31 +02005817void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5818{
5819 struct mgmt_ev_new_irk ev;
5820
5821 memset(&ev, 0, sizeof(ev));
5822
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005823 /* For identity resolving keys from devices that are already
5824 * using a public address or static random address, do not
5825 * ask for storing this key. The identity resolving key really
5826 * is only mandatory for devices using resovlable random
5827 * addresses.
5828 *
5829 * Storing all identity resolving keys has the downside that
5830 * they will be also loaded on next boot of they system. More
5831 * identity resolving keys, means more time during scanning is
5832 * needed to actually resolve these addresses.
5833 */
5834 if (bacmp(&irk->rpa, BDADDR_ANY))
5835 ev.store_hint = 0x01;
5836 else
5837 ev.store_hint = 0x00;
5838
Johan Hedberg95fbac82014-02-19 15:18:31 +02005839 bacpy(&ev.rpa, &irk->rpa);
5840 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5841 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5842 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5843
5844 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5845}
5846
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005847void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5848 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005849{
5850 struct mgmt_ev_new_csrk ev;
5851
5852 memset(&ev, 0, sizeof(ev));
5853
5854 /* Devices using resolvable or non-resolvable random addresses
5855 * without providing an indentity resolving key don't require
5856 * to store signature resolving keys. Their addresses will change
5857 * the next time around.
5858 *
5859 * Only when a remote device provides an identity address
5860 * make sure the signature resolving key is stored. So allow
5861 * static random and public addresses here.
5862 */
5863 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5864 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5865 ev.store_hint = 0x00;
5866 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005867 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005868
5869 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5870 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5871 ev.key.master = csrk->master;
5872 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5873
5874 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5875}
5876
Andre Guedesffb5a8272014-07-01 18:10:11 -03005877void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005878 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5879 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005880{
5881 struct mgmt_ev_new_conn_param ev;
5882
Johan Hedbergc103aea2014-07-02 17:37:34 +03005883 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5884 return;
5885
Andre Guedesffb5a8272014-07-01 18:10:11 -03005886 memset(&ev, 0, sizeof(ev));
5887 bacpy(&ev.addr.bdaddr, bdaddr);
5888 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005889 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005890 ev.min_interval = cpu_to_le16(min_interval);
5891 ev.max_interval = cpu_to_le16(max_interval);
5892 ev.latency = cpu_to_le16(latency);
5893 ev.timeout = cpu_to_le16(timeout);
5894
5895 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5896}
5897
Marcel Holtmann94933992013-10-15 10:26:39 -07005898static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5899 u8 data_len)
5900{
5901 eir[eir_len++] = sizeof(type) + data_len;
5902 eir[eir_len++] = type;
5903 memcpy(&eir[eir_len], data, data_len);
5904 eir_len += data_len;
5905
5906 return eir_len;
5907}
5908
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005909void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5910 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5911 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005912{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005913 char buf[512];
5914 struct mgmt_ev_device_connected *ev = (void *) buf;
5915 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005916
Johan Hedbergb644ba32012-01-17 21:48:47 +02005917 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005918 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005919
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005920 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005921
Johan Hedbergb644ba32012-01-17 21:48:47 +02005922 if (name_len > 0)
5923 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005924 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005925
5926 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005927 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005928 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005929
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005930 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005931
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005932 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5933 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005934}
5935
Johan Hedberg8962ee72011-01-20 12:40:27 +02005936static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5937{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005938 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005939 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005940 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005941
Johan Hedberg88c3df12012-02-09 14:27:38 +02005942 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5943 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005944
Johan Hedbergaee9b212012-02-18 15:07:59 +02005945 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005946 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005947
5948 *sk = cmd->sk;
5949 sock_hold(*sk);
5950
Johan Hedberga664b5b2011-02-19 12:06:02 -03005951 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005952}
5953
Johan Hedberg124f6e32012-02-09 13:50:12 +02005954static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005955{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005956 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005957 struct mgmt_cp_unpair_device *cp = cmd->param;
5958 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005959
5960 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005961 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5962 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005963
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005964 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5965
Johan Hedbergaee9b212012-02-18 15:07:59 +02005966 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005967
5968 mgmt_pending_remove(cmd);
5969}
5970
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005971void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005972 u8 link_type, u8 addr_type, u8 reason,
5973 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005974{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005975 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005976 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005977 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005978
Johan Hedberg8b064a32014-02-24 14:52:22 +02005979 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5980 if (power_off) {
5981 struct mgmt_mode *cp = power_off->param;
5982
5983 /* The connection is still in hci_conn_hash so test for 1
5984 * instead of 0 to know if this is the last one.
5985 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005986 if (!cp->val && hci_conn_count(hdev) == 1) {
5987 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005988 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005989 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005990 }
5991
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005992 if (!mgmt_connected)
5993 return;
5994
Andre Guedes57eb7762013-10-30 19:01:41 -03005995 if (link_type != ACL_LINK && link_type != LE_LINK)
5996 return;
5997
Johan Hedberg744cf192011-11-08 20:40:14 +02005998 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005999
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006000 bacpy(&ev.addr.bdaddr, bdaddr);
6001 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6002 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006003
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006004 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006005
6006 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006007 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006008
Johan Hedberg124f6e32012-02-09 13:50:12 +02006009 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006010 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006011}
6012
Marcel Holtmann78929242013-10-06 23:55:47 -07006013void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6014 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006015{
Andre Guedes3655bba2013-10-30 19:01:40 -03006016 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6017 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006018 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006019 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006020
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006021 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6022 hdev);
6023
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006024 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006025 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006026 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006027
Andre Guedes3655bba2013-10-30 19:01:40 -03006028 cp = cmd->param;
6029
6030 if (bacmp(bdaddr, &cp->addr.bdaddr))
6031 return;
6032
6033 if (cp->addr.type != bdaddr_type)
6034 return;
6035
Johan Hedberg88c3df12012-02-09 14:27:38 +02006036 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006037 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006038
Marcel Holtmann78929242013-10-06 23:55:47 -07006039 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6040 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006041
Johan Hedberga664b5b2011-02-19 12:06:02 -03006042 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006043}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006044
Marcel Holtmann445608d2013-10-06 23:55:48 -07006045void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6046 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006047{
6048 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006049 struct pending_cmd *power_off;
6050
6051 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6052 if (power_off) {
6053 struct mgmt_mode *cp = power_off->param;
6054
6055 /* The connection is still in hci_conn_hash so test for 1
6056 * instead of 0 to know if this is the last one.
6057 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006058 if (!cp->val && hci_conn_count(hdev) == 1) {
6059 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006060 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006061 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006062 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006063
Johan Hedberg4c659c32011-11-07 23:13:39 +02006064 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006065 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006066 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006067
Marcel Holtmann445608d2013-10-06 23:55:48 -07006068 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006069}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006070
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006071void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006072{
6073 struct mgmt_ev_pin_code_request ev;
6074
Johan Hedbergd8457692012-02-17 14:24:57 +02006075 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006076 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006077 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006078
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006079 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006080}
6081
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006082void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6083 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006084{
6085 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006086 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006087
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006088 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006089 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006090 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006091
Johan Hedbergd8457692012-02-17 14:24:57 +02006092 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006093 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006094
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006095 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6096 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006097
Johan Hedberga664b5b2011-02-19 12:06:02 -03006098 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006099}
6100
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006101void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6102 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006103{
6104 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006105 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006106
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006107 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006108 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006109 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006110
Johan Hedbergd8457692012-02-17 14:24:57 +02006111 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006112 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006113
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006114 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6115 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006116
Johan Hedberga664b5b2011-02-19 12:06:02 -03006117 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006118}
Johan Hedberga5c29682011-02-19 12:05:57 -03006119
Johan Hedberg744cf192011-11-08 20:40:14 +02006120int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006121 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006122 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006123{
6124 struct mgmt_ev_user_confirm_request ev;
6125
Johan Hedberg744cf192011-11-08 20:40:14 +02006126 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006127
Johan Hedberg272d90d2012-02-09 15:26:12 +02006128 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006129 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006130 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006131 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006132
Johan Hedberg744cf192011-11-08 20:40:14 +02006133 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006134 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006135}
6136
Johan Hedberg272d90d2012-02-09 15:26:12 +02006137int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006138 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006139{
6140 struct mgmt_ev_user_passkey_request ev;
6141
6142 BT_DBG("%s", hdev->name);
6143
Johan Hedberg272d90d2012-02-09 15:26:12 +02006144 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006145 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006146
6147 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006148 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006149}
6150
Brian Gix0df4c182011-11-16 13:53:13 -08006151static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006152 u8 link_type, u8 addr_type, u8 status,
6153 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006154{
6155 struct pending_cmd *cmd;
6156 struct mgmt_rp_user_confirm_reply rp;
6157 int err;
6158
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006159 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006160 if (!cmd)
6161 return -ENOENT;
6162
Johan Hedberg272d90d2012-02-09 15:26:12 +02006163 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006164 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006165 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006166 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006167
Johan Hedberga664b5b2011-02-19 12:06:02 -03006168 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006169
6170 return err;
6171}
6172
Johan Hedberg744cf192011-11-08 20:40:14 +02006173int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006174 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006175{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006176 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006177 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006178}
6179
Johan Hedberg272d90d2012-02-09 15:26:12 +02006180int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006181 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006182{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006183 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006184 status,
6185 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006186}
Johan Hedberg2a611692011-02-19 12:06:00 -03006187
Brian Gix604086b2011-11-23 08:28:33 -08006188int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006189 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006190{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006191 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006192 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006193}
6194
Johan Hedberg272d90d2012-02-09 15:26:12 +02006195int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006196 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006197{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006198 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006199 status,
6200 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006201}
6202
Johan Hedberg92a25252012-09-06 18:39:26 +03006203int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6204 u8 link_type, u8 addr_type, u32 passkey,
6205 u8 entered)
6206{
6207 struct mgmt_ev_passkey_notify ev;
6208
6209 BT_DBG("%s", hdev->name);
6210
6211 bacpy(&ev.addr.bdaddr, bdaddr);
6212 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6213 ev.passkey = __cpu_to_le32(passkey);
6214 ev.entered = entered;
6215
6216 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6217}
6218
Marcel Holtmanne5460992013-10-15 14:26:23 -07006219void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6220 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006221{
6222 struct mgmt_ev_auth_failed ev;
6223
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006224 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006225 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006226 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006227
Marcel Holtmanne5460992013-10-15 14:26:23 -07006228 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006229}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006230
Marcel Holtmann464996a2013-10-15 14:26:24 -07006231void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006232{
6233 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006234 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006235
6236 if (status) {
6237 u8 mgmt_err = mgmt_status(status);
6238 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006239 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006240 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006241 }
6242
Marcel Holtmann464996a2013-10-15 14:26:24 -07006243 if (test_bit(HCI_AUTH, &hdev->flags))
6244 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6245 &hdev->dev_flags);
6246 else
6247 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6248 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006249
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006250 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006251 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006252
Johan Hedberg47990ea2012-02-22 11:58:37 +02006253 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006254 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006255
6256 if (match.sk)
6257 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006258}
6259
Johan Hedberg890ea892013-03-15 17:06:52 -05006260static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006261{
Johan Hedberg890ea892013-03-15 17:06:52 -05006262 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006263 struct hci_cp_write_eir cp;
6264
Johan Hedberg976eb202012-10-24 21:12:01 +03006265 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006266 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006267
Johan Hedbergc80da272012-02-22 15:38:48 +02006268 memset(hdev->eir, 0, sizeof(hdev->eir));
6269
Johan Hedbergcacaf522012-02-21 00:52:42 +02006270 memset(&cp, 0, sizeof(cp));
6271
Johan Hedberg890ea892013-03-15 17:06:52 -05006272 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006273}
6274
Marcel Holtmann3e248562013-10-15 14:26:25 -07006275void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006276{
6277 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006278 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006279 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006280
6281 if (status) {
6282 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006283
6284 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006285 &hdev->dev_flags)) {
6286 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006287 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006288 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006289
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006290 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6291 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006292 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006293 }
6294
6295 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006296 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006297 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006298 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6299 if (!changed)
6300 changed = test_and_clear_bit(HCI_HS_ENABLED,
6301 &hdev->dev_flags);
6302 else
6303 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006304 }
6305
6306 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6307
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006308 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006309 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006310
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006311 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006312 sock_put(match.sk);
6313
Johan Hedberg890ea892013-03-15 17:06:52 -05006314 hci_req_init(&req, hdev);
6315
Johan Hedberg37699722014-06-24 14:00:27 +03006316 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6317 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6318 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6319 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006320 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006321 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006322 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006323 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006324
6325 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006326}
6327
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006328void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6329{
6330 struct cmd_lookup match = { NULL, hdev };
6331 bool changed = false;
6332
6333 if (status) {
6334 u8 mgmt_err = mgmt_status(status);
6335
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006336 if (enable) {
6337 if (test_and_clear_bit(HCI_SC_ENABLED,
6338 &hdev->dev_flags))
6339 new_settings(hdev, NULL);
6340 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6341 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006342
6343 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6344 cmd_status_rsp, &mgmt_err);
6345 return;
6346 }
6347
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006348 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006349 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006350 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006351 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006352 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6353 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006354
6355 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6356 settings_rsp, &match);
6357
6358 if (changed)
6359 new_settings(hdev, match.sk);
6360
6361 if (match.sk)
6362 sock_put(match.sk);
6363}
6364
Johan Hedberg92da6092013-03-15 17:06:55 -05006365static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006366{
6367 struct cmd_lookup *match = data;
6368
Johan Hedberg90e70452012-02-23 23:09:40 +02006369 if (match->sk == NULL) {
6370 match->sk = cmd->sk;
6371 sock_hold(match->sk);
6372 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006373}
6374
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006375void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6376 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006377{
Johan Hedberg90e70452012-02-23 23:09:40 +02006378 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006379
Johan Hedberg92da6092013-03-15 17:06:55 -05006380 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6381 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6382 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006383
6384 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006385 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6386 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006387
6388 if (match.sk)
6389 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006390}
6391
Marcel Holtmann7667da32013-10-15 14:26:27 -07006392void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006393{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006394 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006395 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006396
Johan Hedberg13928972013-03-15 17:07:00 -05006397 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006398 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006399
6400 memset(&ev, 0, sizeof(ev));
6401 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006402 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006403
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006404 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006405 if (!cmd) {
6406 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006407
Johan Hedberg13928972013-03-15 17:07:00 -05006408 /* If this is a HCI command related to powering on the
6409 * HCI dev don't send any mgmt signals.
6410 */
6411 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006412 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006413 }
6414
Marcel Holtmann7667da32013-10-15 14:26:27 -07006415 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6416 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006417}
Szymon Jancc35938b2011-03-22 13:12:21 +01006418
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006419void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6420 u8 *randomizer192, u8 *hash256,
6421 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006422{
6423 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006424
Johan Hedberg744cf192011-11-08 20:40:14 +02006425 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006426
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006427 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006428 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006429 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006430
6431 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006432 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6433 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006434 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006435 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6436 hash256 && randomizer256) {
6437 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006438
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006439 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6440 memcpy(rp.randomizer192, randomizer192,
6441 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006442
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006443 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6444 memcpy(rp.randomizer256, randomizer256,
6445 sizeof(rp.randomizer256));
6446
6447 cmd_complete(cmd->sk, hdev->id,
6448 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6449 &rp, sizeof(rp));
6450 } else {
6451 struct mgmt_rp_read_local_oob_data rp;
6452
6453 memcpy(rp.hash, hash192, sizeof(rp.hash));
6454 memcpy(rp.randomizer, randomizer192,
6455 sizeof(rp.randomizer));
6456
6457 cmd_complete(cmd->sk, hdev->id,
6458 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6459 &rp, sizeof(rp));
6460 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006461 }
6462
6463 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006464}
Johan Hedberge17acd42011-03-30 23:57:16 +03006465
Marcel Holtmann901801b2013-10-06 23:55:51 -07006466void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006467 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6468 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006469{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006470 char buf[512];
6471 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006472 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006473 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006474
Andre Guedes12602d02013-04-30 15:29:40 -03006475 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006476 return;
Andre Guedes12602d02013-04-30 15:29:40 -03006477
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006478 /* Make sure that the buffer is big enough. The 5 extra bytes
6479 * are for the potential CoD field.
6480 */
6481 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006482 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006483
Johan Hedberg1dc06092012-01-15 21:01:23 +02006484 memset(buf, 0, sizeof(buf));
6485
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006486 irk = hci_get_irk(hdev, bdaddr, addr_type);
6487 if (irk) {
6488 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6489 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6490 } else {
6491 bacpy(&ev->addr.bdaddr, bdaddr);
6492 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6493 }
6494
Johan Hedberge319d2e2012-01-15 19:51:59 +02006495 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006496 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006497
Johan Hedberg1dc06092012-01-15 21:01:23 +02006498 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006499 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006500
Johan Hedberg1dc06092012-01-15 21:01:23 +02006501 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6502 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006503 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006504
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006505 if (scan_rsp_len > 0)
6506 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6507
6508 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6509 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006510
Marcel Holtmann901801b2013-10-06 23:55:51 -07006511 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006512}
Johan Hedberga88a9652011-03-30 13:18:12 +03006513
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006514void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6515 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006516{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006517 struct mgmt_ev_device_found *ev;
6518 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6519 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006520
Johan Hedbergb644ba32012-01-17 21:48:47 +02006521 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006522
Johan Hedbergb644ba32012-01-17 21:48:47 +02006523 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006524
Johan Hedbergb644ba32012-01-17 21:48:47 +02006525 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006526 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006527 ev->rssi = rssi;
6528
6529 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006530 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006531
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006532 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006533
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006534 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006535}
Johan Hedberg314b2382011-04-27 10:29:57 -04006536
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006537void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006538{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006539 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006540 struct pending_cmd *cmd;
6541
Andre Guedes343fb142011-11-22 17:14:19 -03006542 BT_DBG("%s discovering %u", hdev->name, discovering);
6543
Johan Hedberg164a6e72011-11-01 17:06:44 +02006544 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006545 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006546 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006547 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006548
6549 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006550 u8 type = hdev->discovery.type;
6551
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006552 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6553 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006554 mgmt_pending_remove(cmd);
6555 }
6556
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006557 memset(&ev, 0, sizeof(ev));
6558 ev.type = hdev->discovery.type;
6559 ev.discovering = discovering;
6560
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006561 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006562}
Antti Julku5e762442011-08-25 16:48:02 +03006563
Marcel Holtmann5976e602013-10-06 04:08:14 -07006564static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6565{
6566 BT_DBG("%s status %u", hdev->name, status);
6567
6568 /* Clear the advertising mgmt setting if we failed to re-enable it */
6569 if (status) {
6570 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006571 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006572 }
6573}
6574
6575void mgmt_reenable_advertising(struct hci_dev *hdev)
6576{
6577 struct hci_request req;
6578
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006579 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006580 return;
6581
6582 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6583 return;
6584
6585 hci_req_init(&req, hdev);
6586 enable_advertising(&req);
6587
6588 /* If this fails we have no option but to let user space know
6589 * that we've disabled advertising.
6590 */
6591 if (hci_req_run(&req, adv_enable_complete) < 0) {
6592 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006593 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006594 }
6595}