blob: c01cc5e37a6f062b856f7d5d67945ee06c77abc1 [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 Holtmannedd3896b2014-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 Hedberg84bde9d2012-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 Hedberg84bde9d2012-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;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002471 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2472 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002473 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002474 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002475 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002476
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002477 BT_DBG("request for %s", hdev->name);
2478
2479 if (!lmp_bredr_capable(hdev))
2480 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2481 MGMT_STATUS_NOT_SUPPORTED);
2482
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002483 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002484 if (key_count > max_key_count) {
2485 BT_ERR("load_link_keys: too big key_count value %u",
2486 key_count);
2487 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2488 MGMT_STATUS_INVALID_PARAMS);
2489 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002490
Johan Hedberg86742e12011-11-07 23:13:38 +02002491 expected_len = sizeof(*cp) + key_count *
2492 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002493 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002494 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002495 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002496 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002497 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002498 }
2499
Johan Hedberg4ae14302013-01-20 14:27:13 +02002500 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2501 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2502 MGMT_STATUS_INVALID_PARAMS);
2503
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002504 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002505 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002506
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002507 for (i = 0; i < key_count; i++) {
2508 struct mgmt_link_key_info *key = &cp->keys[i];
2509
Marcel Holtmann8e991132014-01-10 02:07:25 -08002510 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002511 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2512 MGMT_STATUS_INVALID_PARAMS);
2513 }
2514
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002515 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002516
2517 hci_link_keys_clear(hdev);
2518
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002519 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002520 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2521 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002522 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002523 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2524 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002525
2526 if (changed)
2527 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002528
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002529 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002530 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002531
Johan Hedberg58e92932014-06-24 14:00:26 +03002532 /* Always ignore debug keys and require a new pairing if
2533 * the user wants to use them.
2534 */
2535 if (key->type == HCI_LK_DEBUG_COMBINATION)
2536 continue;
2537
Johan Hedberg7652ff62014-06-24 13:15:49 +03002538 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2539 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002540 }
2541
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002542 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002544 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002545
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002546 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002547}
2548
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002549static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002551{
2552 struct mgmt_ev_device_unpaired ev;
2553
2554 bacpy(&ev.addr.bdaddr, bdaddr);
2555 ev.addr.type = addr_type;
2556
2557 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002558 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002559}
2560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002561static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002562 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002563{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002564 struct mgmt_cp_unpair_device *cp = data;
2565 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002566 struct hci_cp_disconnect dc;
2567 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002568 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002569 int err;
2570
Johan Hedberga8a1d192011-11-10 15:54:38 +02002571 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002572 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2573 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002574
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002575 if (!bdaddr_type_is_valid(cp->addr.type))
2576 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2577 MGMT_STATUS_INVALID_PARAMS,
2578 &rp, sizeof(rp));
2579
Johan Hedberg118da702013-01-20 14:27:20 +02002580 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2581 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2582 MGMT_STATUS_INVALID_PARAMS,
2583 &rp, sizeof(rp));
2584
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002585 hci_dev_lock(hdev);
2586
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002587 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002588 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002589 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002590 goto unlock;
2591 }
2592
Johan Hedberge0b2b272014-02-18 17:14:31 +02002593 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002594 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002595 } else {
2596 u8 addr_type;
2597
2598 if (cp->addr.type == BDADDR_LE_PUBLIC)
2599 addr_type = ADDR_LE_DEV_PUBLIC;
2600 else
2601 addr_type = ADDR_LE_DEV_RANDOM;
2602
Johan Hedberga7ec7332014-02-18 17:14:35 +02002603 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2604
Andre Guedesa9b0a042014-02-26 20:21:52 -03002605 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2606
Johan Hedberge0b2b272014-02-18 17:14:31 +02002607 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2608 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002609
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002610 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002611 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002612 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002613 goto unlock;
2614 }
2615
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002616 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002617 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002618 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002619 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002620 else
2621 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002622 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002623 } else {
2624 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002625 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002626
Johan Hedberga8a1d192011-11-10 15:54:38 +02002627 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002628 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002629 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002630 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002631 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632 }
2633
Johan Hedberg124f6e32012-02-09 13:50:12 +02002634 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002635 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002636 if (!cmd) {
2637 err = -ENOMEM;
2638 goto unlock;
2639 }
2640
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002641 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002642 dc.reason = 0x13; /* Remote User Terminated Connection */
2643 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2644 if (err < 0)
2645 mgmt_pending_remove(cmd);
2646
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002647unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002648 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002649 return err;
2650}
2651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002652static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002653 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002654{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002655 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002656 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002657 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002658 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002659 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002660 int err;
2661
2662 BT_DBG("");
2663
Johan Hedberg06a63b12013-01-20 14:27:21 +02002664 memset(&rp, 0, sizeof(rp));
2665 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2666 rp.addr.type = cp->addr.type;
2667
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002668 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002669 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2670 MGMT_STATUS_INVALID_PARAMS,
2671 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002673 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002674
2675 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002676 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2677 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002678 goto failed;
2679 }
2680
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002681 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002682 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2683 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002684 goto failed;
2685 }
2686
Andre Guedes591f47f2012-04-24 21:02:49 -03002687 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002688 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2689 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002690 else
2691 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002692
Vishal Agarwalf9607272012-06-13 05:32:43 +05302693 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002694 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2695 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002696 goto failed;
2697 }
2698
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002699 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002700 if (!cmd) {
2701 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002702 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002703 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002704
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002705 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002706 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002707
2708 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2709 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002710 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002711
2712failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002713 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002714 return err;
2715}
2716
Andre Guedes57c14772012-04-24 21:02:50 -03002717static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002718{
2719 switch (link_type) {
2720 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002721 switch (addr_type) {
2722 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002723 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002724
Johan Hedberg48264f02011-11-09 13:58:58 +02002725 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002726 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002727 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002728 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002729
Johan Hedberg4c659c32011-11-07 23:13:39 +02002730 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002731 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002732 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002733 }
2734}
2735
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002736static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2737 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002738{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002739 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002740 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002741 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002742 int err;
2743 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002744
2745 BT_DBG("");
2746
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002747 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002748
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002749 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002750 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002751 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002752 goto unlock;
2753 }
2754
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002755 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002756 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2757 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002758 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002759 }
2760
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002761 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002762 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002763 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002764 err = -ENOMEM;
2765 goto unlock;
2766 }
2767
Johan Hedberg2784eb42011-01-21 13:56:35 +02002768 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002769 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002770 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2771 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002772 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002773 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002774 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002775 continue;
2776 i++;
2777 }
2778
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002779 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002780
Johan Hedberg4c659c32011-11-07 23:13:39 +02002781 /* Recalculate length in case of filtered SCO connections, etc */
2782 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002783
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002784 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002785 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002786
Johan Hedberga38528f2011-01-22 06:46:43 +02002787 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002788
2789unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002790 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002791 return err;
2792}
2793
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002794static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002795 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002796{
2797 struct pending_cmd *cmd;
2798 int err;
2799
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002800 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002801 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002802 if (!cmd)
2803 return -ENOMEM;
2804
Johan Hedbergd8457692012-02-17 14:24:57 +02002805 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002806 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002807 if (err < 0)
2808 mgmt_pending_remove(cmd);
2809
2810 return err;
2811}
2812
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002813static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002814 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002815{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002816 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002817 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002818 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002819 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002820 int err;
2821
2822 BT_DBG("");
2823
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002824 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002825
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002826 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002827 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002828 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002829 goto failed;
2830 }
2831
Johan Hedbergd8457692012-02-17 14:24:57 +02002832 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002833 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002834 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002835 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002836 goto failed;
2837 }
2838
2839 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002840 struct mgmt_cp_pin_code_neg_reply ncp;
2841
2842 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002843
2844 BT_ERR("PIN code is not 16 bytes long");
2845
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002846 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002847 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002848 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002849 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002850
2851 goto failed;
2852 }
2853
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002854 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002855 if (!cmd) {
2856 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002857 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002858 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002859
Johan Hedbergd8457692012-02-17 14:24:57 +02002860 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002861 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002862 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002863
2864 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2865 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002866 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002867
2868failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002869 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002870 return err;
2871}
2872
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002873static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2874 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002875{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002876 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002877
2878 BT_DBG("");
2879
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002880 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2881 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2882 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2883
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002884 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002885
2886 hdev->io_capability = cp->io_capability;
2887
2888 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002889 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002890
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002891 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002892
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002893 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2894 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002895}
2896
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002897static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002898{
2899 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002900 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002901
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002902 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002903 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2904 continue;
2905
Johan Hedberge9a416b2011-02-19 12:05:56 -03002906 if (cmd->user_data != conn)
2907 continue;
2908
2909 return cmd;
2910 }
2911
2912 return NULL;
2913}
2914
2915static void pairing_complete(struct pending_cmd *cmd, u8 status)
2916{
2917 struct mgmt_rp_pair_device rp;
2918 struct hci_conn *conn = cmd->user_data;
2919
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002920 bacpy(&rp.addr.bdaddr, &conn->dst);
2921 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002922
Johan Hedbergaee9b212012-02-18 15:07:59 +02002923 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002924 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002925
2926 /* So we don't get further callbacks for this connection */
2927 conn->connect_cfm_cb = NULL;
2928 conn->security_cfm_cb = NULL;
2929 conn->disconn_cfm_cb = NULL;
2930
David Herrmann76a68ba2013-04-06 20:28:37 +02002931 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002932
Johan Hedberga664b5b2011-02-19 12:06:02 -03002933 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002934}
2935
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002936void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2937{
2938 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2939 struct pending_cmd *cmd;
2940
2941 cmd = find_pairing(conn);
2942 if (cmd)
2943 pairing_complete(cmd, status);
2944}
2945
Johan Hedberge9a416b2011-02-19 12:05:56 -03002946static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2947{
2948 struct pending_cmd *cmd;
2949
2950 BT_DBG("status %u", status);
2951
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002952 cmd = find_pairing(conn);
2953 if (!cmd)
2954 BT_DBG("Unable to find a pending command");
2955 else
Johan Hedberge2113262012-02-18 15:20:03 +02002956 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002957}
2958
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002959static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302960{
2961 struct pending_cmd *cmd;
2962
2963 BT_DBG("status %u", status);
2964
2965 if (!status)
2966 return;
2967
2968 cmd = find_pairing(conn);
2969 if (!cmd)
2970 BT_DBG("Unable to find a pending command");
2971 else
2972 pairing_complete(cmd, mgmt_status(status));
2973}
2974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002975static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002977{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002978 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002979 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002980 struct pending_cmd *cmd;
2981 u8 sec_level, auth_type;
2982 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002983 int err;
2984
2985 BT_DBG("");
2986
Szymon Jancf950a30e2013-01-18 12:48:07 +01002987 memset(&rp, 0, sizeof(rp));
2988 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2989 rp.addr.type = cp->addr.type;
2990
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002991 if (!bdaddr_type_is_valid(cp->addr.type))
2992 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2993 MGMT_STATUS_INVALID_PARAMS,
2994 &rp, sizeof(rp));
2995
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002996 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2997 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2998 MGMT_STATUS_INVALID_PARAMS,
2999 &rp, sizeof(rp));
3000
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003001 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003002
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003003 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003004 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3005 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003006 goto unlock;
3007 }
3008
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003009 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003010 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003011
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003012 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003013 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3014 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003015 } else {
3016 u8 addr_type;
3017
3018 /* Convert from L2CAP channel address type to HCI address type
3019 */
3020 if (cp->addr.type == BDADDR_LE_PUBLIC)
3021 addr_type = ADDR_LE_DEV_PUBLIC;
3022 else
3023 addr_type = ADDR_LE_DEV_RANDOM;
3024
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003025 /* When pairing a new device, it is expected to remember
3026 * this device for future connections. Adding the connection
3027 * parameter information ahead of time allows tracking
3028 * of the slave preferred values and will speed up any
3029 * further connection establishment.
3030 *
3031 * If connection parameters already exist, then they
3032 * will be kept and this function does nothing.
3033 */
3034 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3035
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003036 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003037 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003038 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003039
Ville Tervo30e76272011-02-22 16:10:53 -03003040 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003041 int status;
3042
3043 if (PTR_ERR(conn) == -EBUSY)
3044 status = MGMT_STATUS_BUSY;
3045 else
3046 status = MGMT_STATUS_CONNECT_FAILED;
3047
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003048 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003049 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003050 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003051 goto unlock;
3052 }
3053
3054 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003055 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003056 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003057 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003058 goto unlock;
3059 }
3060
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003061 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003062 if (!cmd) {
3063 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003064 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065 goto unlock;
3066 }
3067
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003068 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003069 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003070 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003071 conn->security_cfm_cb = pairing_complete_cb;
3072 conn->disconn_cfm_cb = pairing_complete_cb;
3073 } else {
3074 conn->connect_cfm_cb = le_pairing_complete_cb;
3075 conn->security_cfm_cb = le_pairing_complete_cb;
3076 conn->disconn_cfm_cb = le_pairing_complete_cb;
3077 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003078
Johan Hedberge9a416b2011-02-19 12:05:56 -03003079 conn->io_capability = cp->io_cap;
3080 cmd->user_data = conn;
3081
3082 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003083 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084 pairing_complete(cmd, 0);
3085
3086 err = 0;
3087
3088unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003089 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090 return err;
3091}
3092
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003093static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3094 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003095{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003096 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003097 struct pending_cmd *cmd;
3098 struct hci_conn *conn;
3099 int err;
3100
3101 BT_DBG("");
3102
Johan Hedberg28424702012-02-02 04:02:29 +02003103 hci_dev_lock(hdev);
3104
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003105 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003106 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003107 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003108 goto unlock;
3109 }
3110
Johan Hedberg28424702012-02-02 04:02:29 +02003111 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3112 if (!cmd) {
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 conn = cmd->user_data;
3119
3120 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003121 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003122 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003123 goto unlock;
3124 }
3125
3126 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3127
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003128 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003130unlock:
3131 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003132 return err;
3133}
3134
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003135static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003136 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003137 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003138{
Johan Hedberga5c29682011-02-19 12:05:57 -03003139 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003140 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003141 int err;
3142
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003143 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003144
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003145 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003146 err = cmd_complete(sk, hdev->id, mgmt_op,
3147 MGMT_STATUS_NOT_POWERED, addr,
3148 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003149 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003150 }
3151
Johan Hedberg1707c602013-03-15 17:07:15 -05003152 if (addr->type == BDADDR_BREDR)
3153 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003154 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003155 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003156
Johan Hedberg272d90d2012-02-09 15:26:12 +02003157 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003158 err = cmd_complete(sk, hdev->id, mgmt_op,
3159 MGMT_STATUS_NOT_CONNECTED, addr,
3160 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003161 goto done;
3162 }
3163
Johan Hedberg1707c602013-03-15 17:07:15 -05003164 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003165 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003166 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003167 err = cmd_complete(sk, hdev->id, mgmt_op,
3168 MGMT_STATUS_SUCCESS, addr,
3169 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003170 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003171 err = cmd_complete(sk, hdev->id, mgmt_op,
3172 MGMT_STATUS_FAILED, addr,
3173 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003174
Brian Gix47c15e22011-11-16 13:53:14 -08003175 goto done;
3176 }
3177
Johan Hedberg1707c602013-03-15 17:07:15 -05003178 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003179 if (!cmd) {
3180 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003181 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003182 }
3183
Brian Gix0df4c182011-11-16 13:53:13 -08003184 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003185 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3186 struct hci_cp_user_passkey_reply cp;
3187
Johan Hedberg1707c602013-03-15 17:07:15 -05003188 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003189 cp.passkey = passkey;
3190 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3191 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003192 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3193 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003194
Johan Hedberga664b5b2011-02-19 12:06:02 -03003195 if (err < 0)
3196 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003197
Brian Gix0df4c182011-11-16 13:53:13 -08003198done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003199 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003200 return err;
3201}
3202
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303203static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3204 void *data, u16 len)
3205{
3206 struct mgmt_cp_pin_code_neg_reply *cp = data;
3207
3208 BT_DBG("");
3209
Johan Hedberg1707c602013-03-15 17:07:15 -05003210 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303211 MGMT_OP_PIN_CODE_NEG_REPLY,
3212 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3213}
3214
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003215static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3216 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003217{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003218 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003219
3220 BT_DBG("");
3221
3222 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003223 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003224 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003225
Johan Hedberg1707c602013-03-15 17:07:15 -05003226 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003227 MGMT_OP_USER_CONFIRM_REPLY,
3228 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003229}
3230
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003231static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003232 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003233{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003234 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003235
3236 BT_DBG("");
3237
Johan Hedberg1707c602013-03-15 17:07:15 -05003238 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003239 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3240 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003241}
3242
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003243static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3244 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003245{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003246 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003247
3248 BT_DBG("");
3249
Johan Hedberg1707c602013-03-15 17:07:15 -05003250 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003251 MGMT_OP_USER_PASSKEY_REPLY,
3252 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003253}
3254
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003255static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003256 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003257{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003258 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003259
3260 BT_DBG("");
3261
Johan Hedberg1707c602013-03-15 17:07:15 -05003262 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003263 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3264 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003265}
3266
Johan Hedberg13928972013-03-15 17:07:00 -05003267static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003268{
Johan Hedberg13928972013-03-15 17:07:00 -05003269 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003270 struct hci_cp_write_local_name cp;
3271
Johan Hedberg13928972013-03-15 17:07:00 -05003272 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003273
Johan Hedberg890ea892013-03-15 17:06:52 -05003274 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003275}
3276
Johan Hedberg13928972013-03-15 17:07:00 -05003277static void set_name_complete(struct hci_dev *hdev, u8 status)
3278{
3279 struct mgmt_cp_set_local_name *cp;
3280 struct pending_cmd *cmd;
3281
3282 BT_DBG("status 0x%02x", status);
3283
3284 hci_dev_lock(hdev);
3285
3286 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3287 if (!cmd)
3288 goto unlock;
3289
3290 cp = cmd->param;
3291
3292 if (status)
3293 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3294 mgmt_status(status));
3295 else
3296 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3297 cp, sizeof(*cp));
3298
3299 mgmt_pending_remove(cmd);
3300
3301unlock:
3302 hci_dev_unlock(hdev);
3303}
3304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003307{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003308 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003309 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003310 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003311 int err;
3312
3313 BT_DBG("");
3314
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003315 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003316
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003317 /* If the old values are the same as the new ones just return a
3318 * direct command complete event.
3319 */
3320 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3321 !memcmp(hdev->short_name, cp->short_name,
3322 sizeof(hdev->short_name))) {
3323 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3324 data, len);
3325 goto failed;
3326 }
3327
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003328 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003329
Johan Hedbergb5235a62012-02-21 14:32:24 +02003330 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003331 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003332
3333 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003334 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003335 if (err < 0)
3336 goto failed;
3337
3338 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003339 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003340
Johan Hedbergb5235a62012-02-21 14:32:24 +02003341 goto failed;
3342 }
3343
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003344 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003345 if (!cmd) {
3346 err = -ENOMEM;
3347 goto failed;
3348 }
3349
Johan Hedberg13928972013-03-15 17:07:00 -05003350 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3351
Johan Hedberg890ea892013-03-15 17:06:52 -05003352 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003353
3354 if (lmp_bredr_capable(hdev)) {
3355 update_name(&req);
3356 update_eir(&req);
3357 }
3358
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003359 /* The name is stored in the scan response data and so
3360 * no need to udpate the advertising data here.
3361 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003362 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003363 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003364
Johan Hedberg13928972013-03-15 17:07:00 -05003365 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003366 if (err < 0)
3367 mgmt_pending_remove(cmd);
3368
3369failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003370 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003371 return err;
3372}
3373
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003374static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003375 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003376{
Szymon Jancc35938b2011-03-22 13:12:21 +01003377 struct pending_cmd *cmd;
3378 int err;
3379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003380 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003381
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003382 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003383
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003384 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003385 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003386 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003387 goto unlock;
3388 }
3389
Andre Guedes9a1a1992012-07-24 15:03:48 -03003390 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003391 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003392 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003393 goto unlock;
3394 }
3395
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003396 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003397 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003399 goto unlock;
3400 }
3401
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003402 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003403 if (!cmd) {
3404 err = -ENOMEM;
3405 goto unlock;
3406 }
3407
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003408 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3409 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3410 0, NULL);
3411 else
3412 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3413
Szymon Jancc35938b2011-03-22 13:12:21 +01003414 if (err < 0)
3415 mgmt_pending_remove(cmd);
3416
3417unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003418 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003419 return err;
3420}
3421
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003422static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003423 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003424{
Szymon Janc2763eda2011-03-22 13:12:22 +01003425 int err;
3426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003427 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003428
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003429 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003430
Marcel Holtmannec109112014-01-10 02:07:30 -08003431 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3432 struct mgmt_cp_add_remote_oob_data *cp = data;
3433 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003434
Marcel Holtmannec109112014-01-10 02:07:30 -08003435 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3436 cp->hash, cp->randomizer);
3437 if (err < 0)
3438 status = MGMT_STATUS_FAILED;
3439 else
3440 status = MGMT_STATUS_SUCCESS;
3441
3442 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3443 status, &cp->addr, sizeof(cp->addr));
3444 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3445 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3446 u8 status;
3447
3448 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3449 cp->hash192,
3450 cp->randomizer192,
3451 cp->hash256,
3452 cp->randomizer256);
3453 if (err < 0)
3454 status = MGMT_STATUS_FAILED;
3455 else
3456 status = MGMT_STATUS_SUCCESS;
3457
3458 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3459 status, &cp->addr, sizeof(cp->addr));
3460 } else {
3461 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3462 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3463 MGMT_STATUS_INVALID_PARAMS);
3464 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003465
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003466 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003467 return err;
3468}
3469
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003470static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003471 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003472{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003473 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003474 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003475 int err;
3476
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003477 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003478
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003479 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003480
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003481 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003482 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003483 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003484 else
Szymon Janca6785be2012-12-13 15:11:21 +01003485 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003487 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003489
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003490 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003491 return err;
3492}
3493
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003494static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3495{
3496 struct pending_cmd *cmd;
3497 u8 type;
3498 int err;
3499
3500 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3501
3502 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3503 if (!cmd)
3504 return -ENOENT;
3505
3506 type = hdev->discovery.type;
3507
3508 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3509 &type, sizeof(type));
3510 mgmt_pending_remove(cmd);
3511
3512 return err;
3513}
3514
Andre Guedes7c307722013-04-30 15:29:28 -03003515static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3516{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003517 unsigned long timeout = 0;
3518
Andre Guedes7c307722013-04-30 15:29:28 -03003519 BT_DBG("status %d", status);
3520
3521 if (status) {
3522 hci_dev_lock(hdev);
3523 mgmt_start_discovery_failed(hdev, status);
3524 hci_dev_unlock(hdev);
3525 return;
3526 }
3527
3528 hci_dev_lock(hdev);
3529 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3530 hci_dev_unlock(hdev);
3531
3532 switch (hdev->discovery.type) {
3533 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003534 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003535 break;
3536
3537 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003538 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003539 break;
3540
3541 case DISCOV_TYPE_BREDR:
3542 break;
3543
3544 default:
3545 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3546 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003547
3548 if (!timeout)
3549 return;
3550
3551 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003552}
3553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003554static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003555 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003556{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003557 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003558 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003559 struct hci_cp_le_set_scan_param param_cp;
3560 struct hci_cp_le_set_scan_enable enable_cp;
3561 struct hci_cp_inquiry inq_cp;
3562 struct hci_request req;
3563 /* General inquiry access code (GIAC) */
3564 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003565 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003566 int err;
3567
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003568 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003569
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003570 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003571
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003572 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003573 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003574 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003575 goto failed;
3576 }
3577
Andre Guedes642be6c2012-03-21 00:03:37 -03003578 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3579 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3580 MGMT_STATUS_BUSY);
3581 goto failed;
3582 }
3583
Johan Hedbergff9ef572012-01-04 14:23:45 +02003584 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003585 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003586 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003587 goto failed;
3588 }
3589
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003590 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003591 if (!cmd) {
3592 err = -ENOMEM;
3593 goto failed;
3594 }
3595
Andre Guedes4aab14e2012-02-17 20:39:36 -03003596 hdev->discovery.type = cp->type;
3597
Andre Guedes7c307722013-04-30 15:29:28 -03003598 hci_req_init(&req, hdev);
3599
Andre Guedes4aab14e2012-02-17 20:39:36 -03003600 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003601 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003602 status = mgmt_bredr_support(hdev);
3603 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003604 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003605 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003606 mgmt_pending_remove(cmd);
3607 goto failed;
3608 }
3609
Andre Guedes7c307722013-04-30 15:29:28 -03003610 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3611 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3612 MGMT_STATUS_BUSY);
3613 mgmt_pending_remove(cmd);
3614 goto failed;
3615 }
3616
3617 hci_inquiry_cache_flush(hdev);
3618
3619 memset(&inq_cp, 0, sizeof(inq_cp));
3620 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003621 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003622 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003623 break;
3624
3625 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003626 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003627 status = mgmt_le_support(hdev);
3628 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003629 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003630 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003631 mgmt_pending_remove(cmd);
3632 goto failed;
3633 }
3634
Andre Guedes7c307722013-04-30 15:29:28 -03003635 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003636 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003637 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3638 MGMT_STATUS_NOT_SUPPORTED);
3639 mgmt_pending_remove(cmd);
3640 goto failed;
3641 }
3642
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003643 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003644 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3645 MGMT_STATUS_REJECTED);
3646 mgmt_pending_remove(cmd);
3647 goto failed;
3648 }
3649
Andre Guedesc54c3862014-02-26 20:21:50 -03003650 /* If controller is scanning, it means the background scanning
3651 * is running. Thus, we should temporarily stop it in order to
3652 * set the discovery scanning parameters.
3653 */
3654 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3655 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003656
3657 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003658
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003659 /* All active scans will be done with either a resolvable
3660 * private address (when privacy feature has been enabled)
3661 * or unresolvable private address.
3662 */
3663 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003664 if (err < 0) {
3665 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3666 MGMT_STATUS_FAILED);
3667 mgmt_pending_remove(cmd);
3668 goto failed;
3669 }
3670
Andre Guedes7c307722013-04-30 15:29:28 -03003671 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003672 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3673 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003674 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003675 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3676 &param_cp);
3677
3678 memset(&enable_cp, 0, sizeof(enable_cp));
3679 enable_cp.enable = LE_SCAN_ENABLE;
3680 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3681 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3682 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003683 break;
3684
Andre Guedesf39799f2012-02-17 20:39:35 -03003685 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003686 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3687 MGMT_STATUS_INVALID_PARAMS);
3688 mgmt_pending_remove(cmd);
3689 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003690 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003691
Andre Guedes7c307722013-04-30 15:29:28 -03003692 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003693 if (err < 0)
3694 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003695 else
3696 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003697
3698failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003699 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003700 return err;
3701}
3702
Andre Guedes1183fdc2013-04-30 15:29:35 -03003703static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3704{
3705 struct pending_cmd *cmd;
3706 int err;
3707
3708 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3709 if (!cmd)
3710 return -ENOENT;
3711
3712 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3713 &hdev->discovery.type, sizeof(hdev->discovery.type));
3714 mgmt_pending_remove(cmd);
3715
3716 return err;
3717}
3718
Andre Guedes0e05bba2013-04-30 15:29:33 -03003719static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3720{
3721 BT_DBG("status %d", status);
3722
3723 hci_dev_lock(hdev);
3724
3725 if (status) {
3726 mgmt_stop_discovery_failed(hdev, status);
3727 goto unlock;
3728 }
3729
3730 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3731
3732unlock:
3733 hci_dev_unlock(hdev);
3734}
3735
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003736static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003737 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003738{
Johan Hedbergd9306502012-02-20 23:25:18 +02003739 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003740 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003741 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003742 int err;
3743
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003744 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003745
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003746 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003747
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003748 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003749 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003750 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3751 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003752 goto unlock;
3753 }
3754
3755 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003756 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003757 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3758 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003759 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003760 }
3761
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003762 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003763 if (!cmd) {
3764 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003765 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003766 }
3767
Andre Guedes0e05bba2013-04-30 15:29:33 -03003768 hci_req_init(&req, hdev);
3769
Johan Hedberg21a60d32014-06-10 14:05:58 +03003770 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003771
Johan Hedberg21a60d32014-06-10 14:05:58 +03003772 err = hci_req_run(&req, stop_discovery_complete);
3773 if (!err) {
3774 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003775 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003776 }
3777
Johan Hedberg21a60d32014-06-10 14:05:58 +03003778 mgmt_pending_remove(cmd);
3779
3780 /* If no HCI commands were sent we're done */
3781 if (err == -ENODATA) {
3782 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3783 &mgmt_cp->type, sizeof(mgmt_cp->type));
3784 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3785 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003786
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003787unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003788 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003789 return err;
3790}
3791
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003792static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003793 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003794{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003795 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003796 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003797 int err;
3798
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003799 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003800
Johan Hedberg561aafb2012-01-04 13:31:59 +02003801 hci_dev_lock(hdev);
3802
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003803 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003804 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3805 MGMT_STATUS_FAILED, &cp->addr,
3806 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003807 goto failed;
3808 }
3809
Johan Hedberga198e7b2012-02-17 14:27:06 +02003810 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003811 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003812 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3813 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3814 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003815 goto failed;
3816 }
3817
3818 if (cp->name_known) {
3819 e->name_state = NAME_KNOWN;
3820 list_del(&e->list);
3821 } else {
3822 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003823 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003824 }
3825
Johan Hedberge3846622013-01-09 15:29:33 +02003826 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3827 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003828
3829failed:
3830 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003831 return err;
3832}
3833
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003834static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003835 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003836{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003837 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003838 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003839 int err;
3840
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003841 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003842
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003843 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003844 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3845 MGMT_STATUS_INVALID_PARAMS,
3846 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003847
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003848 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003849
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003850 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003851 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003852 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003853 goto done;
3854 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003855
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003856 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3857 sk);
3858 status = MGMT_STATUS_SUCCESS;
3859
3860done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003861 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003862 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003863
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003864 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003865
3866 return err;
3867}
3868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003869static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003870 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003871{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003872 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003873 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003874 int err;
3875
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003876 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003877
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003878 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003879 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3880 MGMT_STATUS_INVALID_PARAMS,
3881 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003882
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003883 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003884
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003885 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003886 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003887 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003888 goto done;
3889 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003890
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003891 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3892 sk);
3893 status = MGMT_STATUS_SUCCESS;
3894
3895done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003896 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003897 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003898
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003899 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003900
3901 return err;
3902}
3903
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003904static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3905 u16 len)
3906{
3907 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003908 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003909 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003910 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003911
3912 BT_DBG("%s", hdev->name);
3913
Szymon Jancc72d4b82012-03-16 16:02:57 +01003914 source = __le16_to_cpu(cp->source);
3915
3916 if (source > 0x0002)
3917 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3918 MGMT_STATUS_INVALID_PARAMS);
3919
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003920 hci_dev_lock(hdev);
3921
Szymon Jancc72d4b82012-03-16 16:02:57 +01003922 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003923 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3924 hdev->devid_product = __le16_to_cpu(cp->product);
3925 hdev->devid_version = __le16_to_cpu(cp->version);
3926
3927 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3928
Johan Hedberg890ea892013-03-15 17:06:52 -05003929 hci_req_init(&req, hdev);
3930 update_eir(&req);
3931 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003932
3933 hci_dev_unlock(hdev);
3934
3935 return err;
3936}
3937
Johan Hedberg4375f102013-09-25 13:26:10 +03003938static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3939{
3940 struct cmd_lookup match = { NULL, hdev };
3941
3942 if (status) {
3943 u8 mgmt_err = mgmt_status(status);
3944
3945 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3946 cmd_status_rsp, &mgmt_err);
3947 return;
3948 }
3949
3950 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3951 &match);
3952
3953 new_settings(hdev, match.sk);
3954
3955 if (match.sk)
3956 sock_put(match.sk);
3957}
3958
Marcel Holtmann21b51872013-10-10 09:47:53 -07003959static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3960 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003961{
3962 struct mgmt_mode *cp = data;
3963 struct pending_cmd *cmd;
3964 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003965 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003966 int err;
3967
3968 BT_DBG("request for %s", hdev->name);
3969
Johan Hedberge6fe7982013-10-02 15:45:22 +03003970 status = mgmt_le_support(hdev);
3971 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003972 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003973 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003974
3975 if (cp->val != 0x00 && cp->val != 0x01)
3976 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3977 MGMT_STATUS_INVALID_PARAMS);
3978
3979 hci_dev_lock(hdev);
3980
3981 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003982 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003983
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003984 /* The following conditions are ones which mean that we should
3985 * not do any HCI communication but directly send a mgmt
3986 * response to user space (after toggling the flag if
3987 * necessary).
3988 */
3989 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003990 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003991 bool changed = false;
3992
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003993 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3994 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003995 changed = true;
3996 }
3997
3998 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3999 if (err < 0)
4000 goto unlock;
4001
4002 if (changed)
4003 err = new_settings(hdev, sk);
4004
4005 goto unlock;
4006 }
4007
4008 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4009 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4010 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4011 MGMT_STATUS_BUSY);
4012 goto unlock;
4013 }
4014
4015 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4016 if (!cmd) {
4017 err = -ENOMEM;
4018 goto unlock;
4019 }
4020
4021 hci_req_init(&req, hdev);
4022
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004023 if (val)
4024 enable_advertising(&req);
4025 else
4026 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004027
4028 err = hci_req_run(&req, set_advertising_complete);
4029 if (err < 0)
4030 mgmt_pending_remove(cmd);
4031
4032unlock:
4033 hci_dev_unlock(hdev);
4034 return err;
4035}
4036
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004037static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4038 void *data, u16 len)
4039{
4040 struct mgmt_cp_set_static_address *cp = data;
4041 int err;
4042
4043 BT_DBG("%s", hdev->name);
4044
Marcel Holtmann62af4442013-10-02 22:10:32 -07004045 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004046 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004047 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004048
4049 if (hdev_is_powered(hdev))
4050 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4051 MGMT_STATUS_REJECTED);
4052
4053 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4054 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4055 return cmd_status(sk, hdev->id,
4056 MGMT_OP_SET_STATIC_ADDRESS,
4057 MGMT_STATUS_INVALID_PARAMS);
4058
4059 /* Two most significant bits shall be set */
4060 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4061 return cmd_status(sk, hdev->id,
4062 MGMT_OP_SET_STATIC_ADDRESS,
4063 MGMT_STATUS_INVALID_PARAMS);
4064 }
4065
4066 hci_dev_lock(hdev);
4067
4068 bacpy(&hdev->static_addr, &cp->bdaddr);
4069
4070 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4071
4072 hci_dev_unlock(hdev);
4073
4074 return err;
4075}
4076
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004077static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4078 void *data, u16 len)
4079{
4080 struct mgmt_cp_set_scan_params *cp = data;
4081 __u16 interval, window;
4082 int err;
4083
4084 BT_DBG("%s", hdev->name);
4085
4086 if (!lmp_le_capable(hdev))
4087 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4088 MGMT_STATUS_NOT_SUPPORTED);
4089
4090 interval = __le16_to_cpu(cp->interval);
4091
4092 if (interval < 0x0004 || interval > 0x4000)
4093 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4094 MGMT_STATUS_INVALID_PARAMS);
4095
4096 window = __le16_to_cpu(cp->window);
4097
4098 if (window < 0x0004 || window > 0x4000)
4099 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4100 MGMT_STATUS_INVALID_PARAMS);
4101
Marcel Holtmann899e1072013-10-14 09:55:32 -07004102 if (window > interval)
4103 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4104 MGMT_STATUS_INVALID_PARAMS);
4105
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004106 hci_dev_lock(hdev);
4107
4108 hdev->le_scan_interval = interval;
4109 hdev->le_scan_window = window;
4110
4111 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4112
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004113 /* If background scan is running, restart it so new parameters are
4114 * loaded.
4115 */
4116 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4117 hdev->discovery.state == DISCOVERY_STOPPED) {
4118 struct hci_request req;
4119
4120 hci_req_init(&req, hdev);
4121
4122 hci_req_add_le_scan_disable(&req);
4123 hci_req_add_le_passive_scan(&req);
4124
4125 hci_req_run(&req, NULL);
4126 }
4127
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004128 hci_dev_unlock(hdev);
4129
4130 return err;
4131}
4132
Johan Hedberg33e38b32013-03-15 17:07:05 -05004133static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4134{
4135 struct pending_cmd *cmd;
4136
4137 BT_DBG("status 0x%02x", status);
4138
4139 hci_dev_lock(hdev);
4140
4141 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4142 if (!cmd)
4143 goto unlock;
4144
4145 if (status) {
4146 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4147 mgmt_status(status));
4148 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004149 struct mgmt_mode *cp = cmd->param;
4150
4151 if (cp->val)
4152 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4153 else
4154 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4155
Johan Hedberg33e38b32013-03-15 17:07:05 -05004156 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4157 new_settings(hdev, cmd->sk);
4158 }
4159
4160 mgmt_pending_remove(cmd);
4161
4162unlock:
4163 hci_dev_unlock(hdev);
4164}
4165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004166static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004167 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004168{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004169 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004170 struct pending_cmd *cmd;
4171 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004172 int err;
4173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004174 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004175
Johan Hedberg56f87902013-10-02 13:43:13 +03004176 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4177 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004178 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4179 MGMT_STATUS_NOT_SUPPORTED);
4180
Johan Hedberga7e80f22013-01-09 16:05:19 +02004181 if (cp->val != 0x00 && cp->val != 0x01)
4182 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4183 MGMT_STATUS_INVALID_PARAMS);
4184
Johan Hedberg5400c042012-02-21 16:40:33 +02004185 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004186 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004187 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004188
4189 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004191 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004192
4193 hci_dev_lock(hdev);
4194
Johan Hedberg05cbf292013-03-15 17:07:07 -05004195 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4196 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4197 MGMT_STATUS_BUSY);
4198 goto unlock;
4199 }
4200
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004201 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4202 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4203 hdev);
4204 goto unlock;
4205 }
4206
Johan Hedberg33e38b32013-03-15 17:07:05 -05004207 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4208 data, len);
4209 if (!cmd) {
4210 err = -ENOMEM;
4211 goto unlock;
4212 }
4213
4214 hci_req_init(&req, hdev);
4215
Johan Hedberg406d7802013-03-15 17:07:09 -05004216 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004217
4218 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004219 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004220 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004221 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004222 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004223 }
4224
Johan Hedberg33e38b32013-03-15 17:07:05 -05004225unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004226 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004227
Antti Julkuf6422ec2011-06-22 13:11:56 +03004228 return err;
4229}
4230
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004231static void set_bredr_scan(struct hci_request *req)
4232{
4233 struct hci_dev *hdev = req->hdev;
4234 u8 scan = 0;
4235
4236 /* Ensure that fast connectable is disabled. This function will
4237 * not do anything if the page scan parameters are already what
4238 * they should be.
4239 */
4240 write_fast_connectable(req, false);
4241
4242 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4243 scan |= SCAN_PAGE;
4244 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4245 scan |= SCAN_INQUIRY;
4246
4247 if (scan)
4248 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4249}
4250
Johan Hedberg0663ca22013-10-02 13:43:14 +03004251static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4252{
4253 struct pending_cmd *cmd;
4254
4255 BT_DBG("status 0x%02x", status);
4256
4257 hci_dev_lock(hdev);
4258
4259 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4260 if (!cmd)
4261 goto unlock;
4262
4263 if (status) {
4264 u8 mgmt_err = mgmt_status(status);
4265
4266 /* We need to restore the flag if related HCI commands
4267 * failed.
4268 */
4269 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4270
4271 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4272 } else {
4273 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4274 new_settings(hdev, cmd->sk);
4275 }
4276
4277 mgmt_pending_remove(cmd);
4278
4279unlock:
4280 hci_dev_unlock(hdev);
4281}
4282
4283static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4284{
4285 struct mgmt_mode *cp = data;
4286 struct pending_cmd *cmd;
4287 struct hci_request req;
4288 int err;
4289
4290 BT_DBG("request for %s", hdev->name);
4291
4292 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4293 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4294 MGMT_STATUS_NOT_SUPPORTED);
4295
4296 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4297 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4298 MGMT_STATUS_REJECTED);
4299
4300 if (cp->val != 0x00 && cp->val != 0x01)
4301 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4302 MGMT_STATUS_INVALID_PARAMS);
4303
4304 hci_dev_lock(hdev);
4305
4306 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4307 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4308 goto unlock;
4309 }
4310
4311 if (!hdev_is_powered(hdev)) {
4312 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004313 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4314 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4315 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4316 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4317 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4318 }
4319
4320 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4321
4322 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4323 if (err < 0)
4324 goto unlock;
4325
4326 err = new_settings(hdev, sk);
4327 goto unlock;
4328 }
4329
4330 /* Reject disabling when powered on */
4331 if (!cp->val) {
4332 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4333 MGMT_STATUS_REJECTED);
4334 goto unlock;
4335 }
4336
4337 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4338 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4339 MGMT_STATUS_BUSY);
4340 goto unlock;
4341 }
4342
4343 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4344 if (!cmd) {
4345 err = -ENOMEM;
4346 goto unlock;
4347 }
4348
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004349 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004350 * generates the correct flags.
4351 */
4352 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4353
4354 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004355
4356 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4357 set_bredr_scan(&req);
4358
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004359 /* Since only the advertising data flags will change, there
4360 * is no need to update the scan response data.
4361 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004362 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004363
Johan Hedberg0663ca22013-10-02 13:43:14 +03004364 err = hci_req_run(&req, set_bredr_complete);
4365 if (err < 0)
4366 mgmt_pending_remove(cmd);
4367
4368unlock:
4369 hci_dev_unlock(hdev);
4370 return err;
4371}
4372
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004373static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4374 void *data, u16 len)
4375{
4376 struct mgmt_mode *cp = data;
4377 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004378 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004379 int err;
4380
4381 BT_DBG("request for %s", hdev->name);
4382
4383 status = mgmt_bredr_support(hdev);
4384 if (status)
4385 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4386 status);
4387
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004388 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004389 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004390 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4391 MGMT_STATUS_NOT_SUPPORTED);
4392
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004393 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004394 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4395 MGMT_STATUS_INVALID_PARAMS);
4396
4397 hci_dev_lock(hdev);
4398
4399 if (!hdev_is_powered(hdev)) {
4400 bool changed;
4401
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004402 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004403 changed = !test_and_set_bit(HCI_SC_ENABLED,
4404 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004405 if (cp->val == 0x02)
4406 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4407 else
4408 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4409 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004410 changed = test_and_clear_bit(HCI_SC_ENABLED,
4411 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004412 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4413 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004414
4415 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4416 if (err < 0)
4417 goto failed;
4418
4419 if (changed)
4420 err = new_settings(hdev, sk);
4421
4422 goto failed;
4423 }
4424
4425 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4426 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4427 MGMT_STATUS_BUSY);
4428 goto failed;
4429 }
4430
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004431 val = !!cp->val;
4432
4433 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4434 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004435 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4436 goto failed;
4437 }
4438
4439 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4440 if (!cmd) {
4441 err = -ENOMEM;
4442 goto failed;
4443 }
4444
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004445 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004446 if (err < 0) {
4447 mgmt_pending_remove(cmd);
4448 goto failed;
4449 }
4450
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004451 if (cp->val == 0x02)
4452 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4453 else
4454 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4455
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004456failed:
4457 hci_dev_unlock(hdev);
4458 return err;
4459}
4460
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004461static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4462 void *data, u16 len)
4463{
4464 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004465 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004466 int err;
4467
4468 BT_DBG("request for %s", hdev->name);
4469
Johan Hedbergb97109792014-06-24 14:00:28 +03004470 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004471 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4472 MGMT_STATUS_INVALID_PARAMS);
4473
4474 hci_dev_lock(hdev);
4475
4476 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004477 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4478 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004479 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004480 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4481 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004482
Johan Hedbergb97109792014-06-24 14:00:28 +03004483 if (cp->val == 0x02)
4484 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4485 &hdev->dev_flags);
4486 else
4487 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4488 &hdev->dev_flags);
4489
4490 if (hdev_is_powered(hdev) && use_changed &&
4491 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4492 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4493 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4494 sizeof(mode), &mode);
4495 }
4496
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004497 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4498 if (err < 0)
4499 goto unlock;
4500
4501 if (changed)
4502 err = new_settings(hdev, sk);
4503
4504unlock:
4505 hci_dev_unlock(hdev);
4506 return err;
4507}
4508
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004509static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4510 u16 len)
4511{
4512 struct mgmt_cp_set_privacy *cp = cp_data;
4513 bool changed;
4514 int err;
4515
4516 BT_DBG("request for %s", hdev->name);
4517
4518 if (!lmp_le_capable(hdev))
4519 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4520 MGMT_STATUS_NOT_SUPPORTED);
4521
4522 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4523 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4524 MGMT_STATUS_INVALID_PARAMS);
4525
4526 if (hdev_is_powered(hdev))
4527 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4528 MGMT_STATUS_REJECTED);
4529
4530 hci_dev_lock(hdev);
4531
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004532 /* If user space supports this command it is also expected to
4533 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4534 */
4535 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4536
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004537 if (cp->privacy) {
4538 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4539 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4540 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4541 } else {
4542 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4543 memset(hdev->irk, 0, sizeof(hdev->irk));
4544 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4545 }
4546
4547 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4548 if (err < 0)
4549 goto unlock;
4550
4551 if (changed)
4552 err = new_settings(hdev, sk);
4553
4554unlock:
4555 hci_dev_unlock(hdev);
4556 return err;
4557}
4558
Johan Hedberg41edf162014-02-18 10:19:35 +02004559static bool irk_is_valid(struct mgmt_irk_info *irk)
4560{
4561 switch (irk->addr.type) {
4562 case BDADDR_LE_PUBLIC:
4563 return true;
4564
4565 case BDADDR_LE_RANDOM:
4566 /* Two most significant bits shall be set */
4567 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4568 return false;
4569 return true;
4570 }
4571
4572 return false;
4573}
4574
4575static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4576 u16 len)
4577{
4578 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004579 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4580 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004581 u16 irk_count, expected_len;
4582 int i, err;
4583
4584 BT_DBG("request for %s", hdev->name);
4585
4586 if (!lmp_le_capable(hdev))
4587 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4588 MGMT_STATUS_NOT_SUPPORTED);
4589
4590 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004591 if (irk_count > max_irk_count) {
4592 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4593 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4594 MGMT_STATUS_INVALID_PARAMS);
4595 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004596
4597 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4598 if (expected_len != len) {
4599 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004600 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004601 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4602 MGMT_STATUS_INVALID_PARAMS);
4603 }
4604
4605 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4606
4607 for (i = 0; i < irk_count; i++) {
4608 struct mgmt_irk_info *key = &cp->irks[i];
4609
4610 if (!irk_is_valid(key))
4611 return cmd_status(sk, hdev->id,
4612 MGMT_OP_LOAD_IRKS,
4613 MGMT_STATUS_INVALID_PARAMS);
4614 }
4615
4616 hci_dev_lock(hdev);
4617
4618 hci_smp_irks_clear(hdev);
4619
4620 for (i = 0; i < irk_count; i++) {
4621 struct mgmt_irk_info *irk = &cp->irks[i];
4622 u8 addr_type;
4623
4624 if (irk->addr.type == BDADDR_LE_PUBLIC)
4625 addr_type = ADDR_LE_DEV_PUBLIC;
4626 else
4627 addr_type = ADDR_LE_DEV_RANDOM;
4628
4629 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4630 BDADDR_ANY);
4631 }
4632
4633 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4634
4635 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4636
4637 hci_dev_unlock(hdev);
4638
4639 return err;
4640}
4641
Johan Hedberg3f706b72013-01-20 14:27:16 +02004642static bool ltk_is_valid(struct mgmt_ltk_info *key)
4643{
4644 if (key->master != 0x00 && key->master != 0x01)
4645 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004646
4647 switch (key->addr.type) {
4648 case BDADDR_LE_PUBLIC:
4649 return true;
4650
4651 case BDADDR_LE_RANDOM:
4652 /* Two most significant bits shall be set */
4653 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4654 return false;
4655 return true;
4656 }
4657
4658 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004659}
4660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004661static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004662 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004663{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004664 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004665 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4666 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004667 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004668 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004669
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004670 BT_DBG("request for %s", hdev->name);
4671
4672 if (!lmp_le_capable(hdev))
4673 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4674 MGMT_STATUS_NOT_SUPPORTED);
4675
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004676 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004677 if (key_count > max_key_count) {
4678 BT_ERR("load_ltks: too big key_count value %u", key_count);
4679 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4680 MGMT_STATUS_INVALID_PARAMS);
4681 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004682
4683 expected_len = sizeof(*cp) + key_count *
4684 sizeof(struct mgmt_ltk_info);
4685 if (expected_len != len) {
4686 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004687 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004688 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004689 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004690 }
4691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004692 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004693
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004694 for (i = 0; i < key_count; i++) {
4695 struct mgmt_ltk_info *key = &cp->keys[i];
4696
Johan Hedberg3f706b72013-01-20 14:27:16 +02004697 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004698 return cmd_status(sk, hdev->id,
4699 MGMT_OP_LOAD_LONG_TERM_KEYS,
4700 MGMT_STATUS_INVALID_PARAMS);
4701 }
4702
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004703 hci_dev_lock(hdev);
4704
4705 hci_smp_ltks_clear(hdev);
4706
4707 for (i = 0; i < key_count; i++) {
4708 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004709 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004710
4711 if (key->addr.type == BDADDR_LE_PUBLIC)
4712 addr_type = ADDR_LE_DEV_PUBLIC;
4713 else
4714 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004715
4716 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004717 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004718 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004719 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004720
Johan Hedberg61b43352014-05-29 19:36:53 +03004721 switch (key->type) {
4722 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004723 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004724 break;
4725 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004726 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004727 break;
4728 default:
4729 continue;
4730 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004731
Johan Hedberg35d70272014-02-19 14:57:47 +02004732 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004733 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004734 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004735 }
4736
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004737 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4738 NULL, 0);
4739
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004740 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004741
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004742 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004743}
4744
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004745struct cmd_conn_lookup {
4746 struct hci_conn *conn;
4747 bool valid_tx_power;
4748 u8 mgmt_status;
4749};
4750
4751static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4752{
4753 struct cmd_conn_lookup *match = data;
4754 struct mgmt_cp_get_conn_info *cp;
4755 struct mgmt_rp_get_conn_info rp;
4756 struct hci_conn *conn = cmd->user_data;
4757
4758 if (conn != match->conn)
4759 return;
4760
4761 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4762
4763 memset(&rp, 0, sizeof(rp));
4764 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4765 rp.addr.type = cp->addr.type;
4766
4767 if (!match->mgmt_status) {
4768 rp.rssi = conn->rssi;
4769
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004770 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004771 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004772 rp.max_tx_power = conn->max_tx_power;
4773 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004774 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004775 rp.max_tx_power = HCI_TX_POWER_INVALID;
4776 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004777 }
4778
4779 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4780 match->mgmt_status, &rp, sizeof(rp));
4781
4782 hci_conn_drop(conn);
4783
4784 mgmt_pending_remove(cmd);
4785}
4786
4787static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4788{
4789 struct hci_cp_read_rssi *cp;
4790 struct hci_conn *conn;
4791 struct cmd_conn_lookup match;
4792 u16 handle;
4793
4794 BT_DBG("status 0x%02x", status);
4795
4796 hci_dev_lock(hdev);
4797
4798 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004799 * otherwise we assume it's not valid. At the moment we assume that
4800 * either both or none of current and max values are valid to keep code
4801 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004802 */
4803 match.valid_tx_power = !status;
4804
4805 /* Commands sent in request are either Read RSSI or Read Transmit Power
4806 * Level so we check which one was last sent to retrieve connection
4807 * handle. Both commands have handle as first parameter so it's safe to
4808 * cast data on the same command struct.
4809 *
4810 * First command sent is always Read RSSI and we fail only if it fails.
4811 * In other case we simply override error to indicate success as we
4812 * already remembered if TX power value is actually valid.
4813 */
4814 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4815 if (!cp) {
4816 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4817 status = 0;
4818 }
4819
4820 if (!cp) {
4821 BT_ERR("invalid sent_cmd in response");
4822 goto unlock;
4823 }
4824
4825 handle = __le16_to_cpu(cp->handle);
4826 conn = hci_conn_hash_lookup_handle(hdev, handle);
4827 if (!conn) {
4828 BT_ERR("unknown handle (%d) in response", handle);
4829 goto unlock;
4830 }
4831
4832 match.conn = conn;
4833 match.mgmt_status = mgmt_status(status);
4834
4835 /* Cache refresh is complete, now reply for mgmt request for given
4836 * connection only.
4837 */
4838 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4839 get_conn_info_complete, &match);
4840
4841unlock:
4842 hci_dev_unlock(hdev);
4843}
4844
4845static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4846 u16 len)
4847{
4848 struct mgmt_cp_get_conn_info *cp = data;
4849 struct mgmt_rp_get_conn_info rp;
4850 struct hci_conn *conn;
4851 unsigned long conn_info_age;
4852 int err = 0;
4853
4854 BT_DBG("%s", hdev->name);
4855
4856 memset(&rp, 0, sizeof(rp));
4857 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4858 rp.addr.type = cp->addr.type;
4859
4860 if (!bdaddr_type_is_valid(cp->addr.type))
4861 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4862 MGMT_STATUS_INVALID_PARAMS,
4863 &rp, sizeof(rp));
4864
4865 hci_dev_lock(hdev);
4866
4867 if (!hdev_is_powered(hdev)) {
4868 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4869 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4870 goto unlock;
4871 }
4872
4873 if (cp->addr.type == BDADDR_BREDR)
4874 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4875 &cp->addr.bdaddr);
4876 else
4877 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4878
4879 if (!conn || conn->state != BT_CONNECTED) {
4880 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4881 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4882 goto unlock;
4883 }
4884
4885 /* To avoid client trying to guess when to poll again for information we
4886 * calculate conn info age as random value between min/max set in hdev.
4887 */
4888 conn_info_age = hdev->conn_info_min_age +
4889 prandom_u32_max(hdev->conn_info_max_age -
4890 hdev->conn_info_min_age);
4891
4892 /* Query controller to refresh cached values if they are too old or were
4893 * never read.
4894 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004895 if (time_after(jiffies, conn->conn_info_timestamp +
4896 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004897 !conn->conn_info_timestamp) {
4898 struct hci_request req;
4899 struct hci_cp_read_tx_power req_txp_cp;
4900 struct hci_cp_read_rssi req_rssi_cp;
4901 struct pending_cmd *cmd;
4902
4903 hci_req_init(&req, hdev);
4904 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4905 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4906 &req_rssi_cp);
4907
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004908 /* For LE links TX power does not change thus we don't need to
4909 * query for it once value is known.
4910 */
4911 if (!bdaddr_type_is_le(cp->addr.type) ||
4912 conn->tx_power == HCI_TX_POWER_INVALID) {
4913 req_txp_cp.handle = cpu_to_le16(conn->handle);
4914 req_txp_cp.type = 0x00;
4915 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4916 sizeof(req_txp_cp), &req_txp_cp);
4917 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004918
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004919 /* Max TX power needs to be read only once per connection */
4920 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4921 req_txp_cp.handle = cpu_to_le16(conn->handle);
4922 req_txp_cp.type = 0x01;
4923 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4924 sizeof(req_txp_cp), &req_txp_cp);
4925 }
4926
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004927 err = hci_req_run(&req, conn_info_refresh_complete);
4928 if (err < 0)
4929 goto unlock;
4930
4931 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4932 data, len);
4933 if (!cmd) {
4934 err = -ENOMEM;
4935 goto unlock;
4936 }
4937
4938 hci_conn_hold(conn);
4939 cmd->user_data = conn;
4940
4941 conn->conn_info_timestamp = jiffies;
4942 } else {
4943 /* Cache is valid, just reply with values cached in hci_conn */
4944 rp.rssi = conn->rssi;
4945 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004946 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004947
4948 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4949 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4950 }
4951
4952unlock:
4953 hci_dev_unlock(hdev);
4954 return err;
4955}
4956
Johan Hedberg95868422014-06-28 17:54:07 +03004957static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
4958{
4959 struct mgmt_cp_get_clock_info *cp;
4960 struct mgmt_rp_get_clock_info rp;
4961 struct hci_cp_read_clock *hci_cp;
4962 struct pending_cmd *cmd;
4963 struct hci_conn *conn;
4964
4965 BT_DBG("%s status %u", hdev->name, status);
4966
4967 hci_dev_lock(hdev);
4968
4969 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
4970 if (!hci_cp)
4971 goto unlock;
4972
4973 if (hci_cp->which) {
4974 u16 handle = __le16_to_cpu(hci_cp->handle);
4975 conn = hci_conn_hash_lookup_handle(hdev, handle);
4976 } else {
4977 conn = NULL;
4978 }
4979
4980 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
4981 if (!cmd)
4982 goto unlock;
4983
4984 cp = cmd->param;
4985
4986 memset(&rp, 0, sizeof(rp));
4987 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
4988
4989 if (status)
4990 goto send_rsp;
4991
4992 rp.local_clock = cpu_to_le32(hdev->clock);
4993
4994 if (conn) {
4995 rp.piconet_clock = cpu_to_le32(conn->clock);
4996 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
4997 }
4998
4999send_rsp:
5000 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5001 &rp, sizeof(rp));
5002 mgmt_pending_remove(cmd);
5003 if (conn)
5004 hci_conn_drop(conn);
5005
5006unlock:
5007 hci_dev_unlock(hdev);
5008}
5009
5010static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5011 u16 len)
5012{
5013 struct mgmt_cp_get_clock_info *cp = data;
5014 struct mgmt_rp_get_clock_info rp;
5015 struct hci_cp_read_clock hci_cp;
5016 struct pending_cmd *cmd;
5017 struct hci_request req;
5018 struct hci_conn *conn;
5019 int err;
5020
5021 BT_DBG("%s", hdev->name);
5022
5023 memset(&rp, 0, sizeof(rp));
5024 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5025 rp.addr.type = cp->addr.type;
5026
5027 if (cp->addr.type != BDADDR_BREDR)
5028 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5029 MGMT_STATUS_INVALID_PARAMS,
5030 &rp, sizeof(rp));
5031
5032 hci_dev_lock(hdev);
5033
5034 if (!hdev_is_powered(hdev)) {
5035 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5036 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5037 goto unlock;
5038 }
5039
5040 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5041 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5042 &cp->addr.bdaddr);
5043 if (!conn || conn->state != BT_CONNECTED) {
5044 err = cmd_complete(sk, hdev->id,
5045 MGMT_OP_GET_CLOCK_INFO,
5046 MGMT_STATUS_NOT_CONNECTED,
5047 &rp, sizeof(rp));
5048 goto unlock;
5049 }
5050 } else {
5051 conn = NULL;
5052 }
5053
5054 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5055 if (!cmd) {
5056 err = -ENOMEM;
5057 goto unlock;
5058 }
5059
5060 hci_req_init(&req, hdev);
5061
5062 memset(&hci_cp, 0, sizeof(hci_cp));
5063 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5064
5065 if (conn) {
5066 hci_conn_hold(conn);
5067 cmd->user_data = conn;
5068
5069 hci_cp.handle = cpu_to_le16(conn->handle);
5070 hci_cp.which = 0x01; /* Piconet clock */
5071 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5072 }
5073
5074 err = hci_req_run(&req, get_clock_info_complete);
5075 if (err < 0)
5076 mgmt_pending_remove(cmd);
5077
5078unlock:
5079 hci_dev_unlock(hdev);
5080 return err;
5081}
5082
Marcel Holtmann8afef092014-06-29 22:28:34 +02005083static void device_added(struct sock *sk, struct hci_dev *hdev,
5084 bdaddr_t *bdaddr, u8 type, u8 action)
5085{
5086 struct mgmt_ev_device_added ev;
5087
5088 bacpy(&ev.addr.bdaddr, bdaddr);
5089 ev.addr.type = type;
5090 ev.action = action;
5091
5092 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5093}
5094
Marcel Holtmann2faade52014-06-29 19:44:03 +02005095static int add_device(struct sock *sk, struct hci_dev *hdev,
5096 void *data, u16 len)
5097{
5098 struct mgmt_cp_add_device *cp = data;
5099 u8 auto_conn, addr_type;
5100 int err;
5101
5102 BT_DBG("%s", hdev->name);
5103
5104 if (!bdaddr_type_is_le(cp->addr.type) ||
5105 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5106 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5107 MGMT_STATUS_INVALID_PARAMS,
5108 &cp->addr, sizeof(cp->addr));
5109
5110 if (cp->action != 0x00 && cp->action != 0x01)
5111 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5112 MGMT_STATUS_INVALID_PARAMS,
5113 &cp->addr, sizeof(cp->addr));
5114
5115 hci_dev_lock(hdev);
5116
5117 if (cp->addr.type == BDADDR_LE_PUBLIC)
5118 addr_type = ADDR_LE_DEV_PUBLIC;
5119 else
5120 addr_type = ADDR_LE_DEV_RANDOM;
5121
5122 if (cp->action)
5123 auto_conn = HCI_AUTO_CONN_ALWAYS;
5124 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005125 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005126
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005127 /* If the connection parameters don't exist for this device,
5128 * they will be created and configured with defaults.
5129 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005130 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5131 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005132 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5133 MGMT_STATUS_FAILED,
5134 &cp->addr, sizeof(cp->addr));
5135 goto unlock;
5136 }
5137
Marcel Holtmann8afef092014-06-29 22:28:34 +02005138 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5139
Marcel Holtmann2faade52014-06-29 19:44:03 +02005140 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5141 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5142
5143unlock:
5144 hci_dev_unlock(hdev);
5145 return err;
5146}
5147
Marcel Holtmann8afef092014-06-29 22:28:34 +02005148static void device_removed(struct sock *sk, struct hci_dev *hdev,
5149 bdaddr_t *bdaddr, u8 type)
5150{
5151 struct mgmt_ev_device_removed ev;
5152
5153 bacpy(&ev.addr.bdaddr, bdaddr);
5154 ev.addr.type = type;
5155
5156 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5157}
5158
Marcel Holtmann2faade52014-06-29 19:44:03 +02005159static int remove_device(struct sock *sk, struct hci_dev *hdev,
5160 void *data, u16 len)
5161{
5162 struct mgmt_cp_remove_device *cp = data;
5163 int err;
5164
5165 BT_DBG("%s", hdev->name);
5166
5167 hci_dev_lock(hdev);
5168
5169 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005170 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005171 u8 addr_type;
5172
5173 if (!bdaddr_type_is_le(cp->addr.type)) {
5174 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5175 MGMT_STATUS_INVALID_PARAMS,
5176 &cp->addr, sizeof(cp->addr));
5177 goto unlock;
5178 }
5179
5180 if (cp->addr.type == BDADDR_LE_PUBLIC)
5181 addr_type = ADDR_LE_DEV_PUBLIC;
5182 else
5183 addr_type = ADDR_LE_DEV_RANDOM;
5184
Johan Hedbergc71593d2014-07-02 17:37:28 +03005185 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5186 addr_type);
5187 if (!params) {
5188 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5189 MGMT_STATUS_INVALID_PARAMS,
5190 &cp->addr, sizeof(cp->addr));
5191 goto unlock;
5192 }
5193
5194 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5195 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5196 MGMT_STATUS_INVALID_PARAMS,
5197 &cp->addr, sizeof(cp->addr));
5198 goto unlock;
5199 }
5200
5201 hci_pend_le_conn_del(hdev, &cp->addr.bdaddr, addr_type);
5202 list_del(&params->list);
5203 kfree(params);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005204
5205 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005206 } else {
5207 if (cp->addr.type) {
5208 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5209 MGMT_STATUS_INVALID_PARAMS,
5210 &cp->addr, sizeof(cp->addr));
5211 goto unlock;
5212 }
5213
Johan Hedbergc71593d2014-07-02 17:37:28 +03005214 hci_conn_params_clear_enabled(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005215 }
5216
5217 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5218 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5219
5220unlock:
5221 hci_dev_unlock(hdev);
5222 return err;
5223}
5224
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005225static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5226 u16 len)
5227{
5228 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005229 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5230 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005231 u16 param_count, expected_len;
5232 int i;
5233
5234 if (!lmp_le_capable(hdev))
5235 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5236 MGMT_STATUS_NOT_SUPPORTED);
5237
5238 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005239 if (param_count > max_param_count) {
5240 BT_ERR("load_conn_param: too big param_count value %u",
5241 param_count);
5242 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5243 MGMT_STATUS_INVALID_PARAMS);
5244 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005245
5246 expected_len = sizeof(*cp) + param_count *
5247 sizeof(struct mgmt_conn_param);
5248 if (expected_len != len) {
5249 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5250 expected_len, len);
5251 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5252 MGMT_STATUS_INVALID_PARAMS);
5253 }
5254
5255 BT_DBG("%s param_count %u", hdev->name, param_count);
5256
5257 hci_dev_lock(hdev);
5258
5259 hci_conn_params_clear_disabled(hdev);
5260
5261 for (i = 0; i < param_count; i++) {
5262 struct mgmt_conn_param *param = &cp->params[i];
5263 struct hci_conn_params *hci_param;
5264 u16 min, max, latency, timeout;
5265 u8 addr_type;
5266
5267 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5268 param->addr.type);
5269
5270 if (param->addr.type == BDADDR_LE_PUBLIC) {
5271 addr_type = ADDR_LE_DEV_PUBLIC;
5272 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5273 addr_type = ADDR_LE_DEV_RANDOM;
5274 } else {
5275 BT_ERR("Ignoring invalid connection parameters");
5276 continue;
5277 }
5278
5279 min = le16_to_cpu(param->min_interval);
5280 max = le16_to_cpu(param->max_interval);
5281 latency = le16_to_cpu(param->latency);
5282 timeout = le16_to_cpu(param->timeout);
5283
5284 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5285 min, max, latency, timeout);
5286
5287 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5288 BT_ERR("Ignoring invalid connection parameters");
5289 continue;
5290 }
5291
5292 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5293 addr_type);
5294 if (!hci_param) {
5295 BT_ERR("Failed to add connection parameters");
5296 continue;
5297 }
5298
5299 hci_param->conn_min_interval = min;
5300 hci_param->conn_max_interval = max;
5301 hci_param->conn_latency = latency;
5302 hci_param->supervision_timeout = timeout;
5303 }
5304
5305 hci_dev_unlock(hdev);
5306
5307 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5308}
5309
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005310static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005311 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5312 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005313 bool var_len;
5314 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005315} mgmt_handlers[] = {
5316 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005317 { read_version, false, MGMT_READ_VERSION_SIZE },
5318 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5319 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5320 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5321 { set_powered, false, MGMT_SETTING_SIZE },
5322 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5323 { set_connectable, false, MGMT_SETTING_SIZE },
5324 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5325 { set_pairable, false, MGMT_SETTING_SIZE },
5326 { set_link_security, false, MGMT_SETTING_SIZE },
5327 { set_ssp, false, MGMT_SETTING_SIZE },
5328 { set_hs, false, MGMT_SETTING_SIZE },
5329 { set_le, false, MGMT_SETTING_SIZE },
5330 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5331 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5332 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5333 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5334 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5335 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5336 { disconnect, false, MGMT_DISCONNECT_SIZE },
5337 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5338 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5339 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5340 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5341 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5342 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5343 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5344 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5345 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5346 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5347 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5348 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005349 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005350 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5351 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5352 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5353 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5354 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5355 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005356 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005357 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005358 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005359 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005360 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005361 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005362 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005363 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005364 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005365 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005366 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005367 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5368 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005369 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5370 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005371};
5372
Johan Hedberg03811012010-12-08 00:21:06 +02005373int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005375 void *buf;
5376 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005377 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005378 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005379 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005380 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005381 int err;
5382
5383 BT_DBG("got %zu bytes", msglen);
5384
5385 if (msglen < sizeof(*hdr))
5386 return -EINVAL;
5387
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005388 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005389 if (!buf)
5390 return -ENOMEM;
5391
5392 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5393 err = -EFAULT;
5394 goto done;
5395 }
5396
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005397 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005398 opcode = __le16_to_cpu(hdr->opcode);
5399 index = __le16_to_cpu(hdr->index);
5400 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005401
5402 if (len != msglen - sizeof(*hdr)) {
5403 err = -EINVAL;
5404 goto done;
5405 }
5406
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005407 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005408 hdev = hci_dev_get(index);
5409 if (!hdev) {
5410 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005411 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005412 goto done;
5413 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005414
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005415 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005416 test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) ||
5417 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005418 err = cmd_status(sk, index, opcode,
5419 MGMT_STATUS_INVALID_INDEX);
5420 goto done;
5421 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005422 }
5423
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005424 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005425 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005426 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005427 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005428 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005429 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005430 }
5431
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005432 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5433 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5434 err = cmd_status(sk, index, opcode,
5435 MGMT_STATUS_INVALID_INDEX);
5436 goto done;
5437 }
5438
5439 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5440 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005441 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005442 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005443 goto done;
5444 }
5445
Johan Hedbergbe22b542012-03-01 22:24:41 +02005446 handler = &mgmt_handlers[opcode];
5447
5448 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005449 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005450 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005451 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005452 goto done;
5453 }
5454
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005455 if (hdev)
5456 mgmt_init_hdev(sk, hdev);
5457
5458 cp = buf + sizeof(*hdr);
5459
Johan Hedbergbe22b542012-03-01 22:24:41 +02005460 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005461 if (err < 0)
5462 goto done;
5463
Johan Hedberg03811012010-12-08 00:21:06 +02005464 err = msglen;
5465
5466done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005467 if (hdev)
5468 hci_dev_put(hdev);
5469
Johan Hedberg03811012010-12-08 00:21:06 +02005470 kfree(buf);
5471 return err;
5472}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005473
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005474void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005475{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005476 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005477 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005478
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005479 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5480 return;
5481
5482 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5483 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5484 else
5485 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005486}
5487
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005488void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005489{
Johan Hedberg5f159032012-03-02 03:13:19 +02005490 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005491
Marcel Holtmann1514b892013-10-06 08:25:01 -07005492 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005493 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005494
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005495 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5496 return;
5497
Johan Hedberg744cf192011-11-08 20:40:14 +02005498 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005499
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02005500 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5501 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5502 else
5503 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005504}
5505
Andre Guedes6046dc32014-02-26 20:21:51 -03005506/* This function requires the caller holds hdev->lock */
5507static void restart_le_auto_conns(struct hci_dev *hdev)
5508{
5509 struct hci_conn_params *p;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005510 bool added = false;
Andre Guedes6046dc32014-02-26 20:21:51 -03005511
5512 list_for_each_entry(p, &hdev->le_conn_params, list) {
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005513 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) {
Andre Guedes6046dc32014-02-26 20:21:51 -03005514 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005515 added = true;
5516 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005517 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005518
5519 /* Calling hci_pend_le_conn_add will actually already trigger
5520 * background scanning when needed. So no need to trigger it
5521 * just another time.
5522 *
5523 * This check is here to avoid an unneeded restart of the
5524 * passive scanning. Since this is during the controller
5525 * power up phase the duplicate filtering is not an issue.
5526 */
5527 if (added)
5528 return;
5529
5530 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005531}
5532
Johan Hedberg229ab392013-03-15 17:06:53 -05005533static void powered_complete(struct hci_dev *hdev, u8 status)
5534{
5535 struct cmd_lookup match = { NULL, hdev };
5536
5537 BT_DBG("status 0x%02x", status);
5538
5539 hci_dev_lock(hdev);
5540
Andre Guedes6046dc32014-02-26 20:21:51 -03005541 restart_le_auto_conns(hdev);
5542
Johan Hedberg229ab392013-03-15 17:06:53 -05005543 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5544
5545 new_settings(hdev, match.sk);
5546
5547 hci_dev_unlock(hdev);
5548
5549 if (match.sk)
5550 sock_put(match.sk);
5551}
5552
Johan Hedberg70da6242013-03-15 17:06:51 -05005553static int powered_update_hci(struct hci_dev *hdev)
5554{
Johan Hedberg890ea892013-03-15 17:06:52 -05005555 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005556 u8 link_sec;
5557
Johan Hedberg890ea892013-03-15 17:06:52 -05005558 hci_req_init(&req, hdev);
5559
Johan Hedberg70da6242013-03-15 17:06:51 -05005560 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5561 !lmp_host_ssp_capable(hdev)) {
5562 u8 ssp = 1;
5563
Johan Hedberg890ea892013-03-15 17:06:52 -05005564 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005565 }
5566
Johan Hedbergc73eee92013-04-19 18:35:21 +03005567 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5568 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005569 struct hci_cp_write_le_host_supported cp;
5570
5571 cp.le = 1;
5572 cp.simul = lmp_le_br_capable(hdev);
5573
5574 /* Check first if we already have the right
5575 * host state (host features set)
5576 */
5577 if (cp.le != lmp_host_le_capable(hdev) ||
5578 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005579 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5580 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005581 }
5582
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005583 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005584 /* Make sure the controller has a good default for
5585 * advertising data. This also applies to the case
5586 * where BR/EDR was toggled during the AUTO_OFF phase.
5587 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005588 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005589 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005590 update_scan_rsp_data(&req);
5591 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005592
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005593 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5594 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005595 }
5596
Johan Hedberg70da6242013-03-15 17:06:51 -05005597 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5598 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005599 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5600 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005601
5602 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005603 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5604 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005605 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005606 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005607 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005608 }
5609
Johan Hedberg229ab392013-03-15 17:06:53 -05005610 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005611}
5612
Johan Hedberg744cf192011-11-08 20:40:14 +02005613int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005614{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005615 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005616 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5617 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005618 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005619
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005620 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5621 return 0;
5622
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005623 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005624 if (powered_update_hci(hdev) == 0)
5625 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005626
Johan Hedberg229ab392013-03-15 17:06:53 -05005627 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5628 &match);
5629 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005630 }
5631
Johan Hedberg229ab392013-03-15 17:06:53 -05005632 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5633 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5634
5635 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5636 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5637 zero_cod, sizeof(zero_cod), NULL);
5638
5639new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005640 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005641
5642 if (match.sk)
5643 sock_put(match.sk);
5644
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005645 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005646}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005647
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005648void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005649{
5650 struct pending_cmd *cmd;
5651 u8 status;
5652
5653 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5654 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005655 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005656
5657 if (err == -ERFKILL)
5658 status = MGMT_STATUS_RFKILLED;
5659 else
5660 status = MGMT_STATUS_FAILED;
5661
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005662 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005663
5664 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005665}
5666
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005667void mgmt_discoverable_timeout(struct hci_dev *hdev)
5668{
5669 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005670
5671 hci_dev_lock(hdev);
5672
5673 /* When discoverable timeout triggers, then just make sure
5674 * the limited discoverable flag is cleared. Even in the case
5675 * of a timeout triggered from general discoverable, it is
5676 * safe to unconditionally clear the flag.
5677 */
5678 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005679 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005680
5681 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005682 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5683 u8 scan = SCAN_PAGE;
5684 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5685 sizeof(scan), &scan);
5686 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005687 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005688 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005689 hci_req_run(&req, NULL);
5690
5691 hdev->discov_timeout = 0;
5692
Johan Hedberg9a43e252013-10-20 19:00:07 +03005693 new_settings(hdev, NULL);
5694
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005695 hci_dev_unlock(hdev);
5696}
5697
Marcel Holtmann86a75642013-10-15 06:33:54 -07005698void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005699{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005700 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005701
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005702 /* Nothing needed here if there's a pending command since that
5703 * commands request completion callback takes care of everything
5704 * necessary.
5705 */
5706 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005707 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005708
Johan Hedbergbd107992014-02-24 14:52:19 +02005709 /* Powering off may clear the scan mode - don't let that interfere */
5710 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5711 return;
5712
Johan Hedberg9a43e252013-10-20 19:00:07 +03005713 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005714 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005715 } else {
5716 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005717 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005718 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005719
Johan Hedberg9a43e252013-10-20 19:00:07 +03005720 if (changed) {
5721 struct hci_request req;
5722
5723 /* In case this change in discoverable was triggered by
5724 * a disabling of connectable there could be a need to
5725 * update the advertising flags.
5726 */
5727 hci_req_init(&req, hdev);
5728 update_adv_data(&req);
5729 hci_req_run(&req, NULL);
5730
Marcel Holtmann86a75642013-10-15 06:33:54 -07005731 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005732 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005733}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005734
Marcel Holtmanna3309162013-10-15 06:33:55 -07005735void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005736{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005737 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005738
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005739 /* Nothing needed here if there's a pending command since that
5740 * commands request completion callback takes care of everything
5741 * necessary.
5742 */
5743 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005744 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005745
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005746 /* Powering off may clear the scan mode - don't let that interfere */
5747 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5748 return;
5749
Marcel Holtmanna3309162013-10-15 06:33:55 -07005750 if (connectable)
5751 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5752 else
5753 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005754
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005755 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005756 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005757}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005758
Johan Hedberg778b2352014-02-24 14:52:17 +02005759void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5760{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005761 /* Powering off may stop advertising - don't let that interfere */
5762 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5763 return;
5764
Johan Hedberg778b2352014-02-24 14:52:17 +02005765 if (advertising)
5766 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5767 else
5768 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5769}
5770
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005771void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005772{
Johan Hedbergca69b792011-11-11 18:10:00 +02005773 u8 mgmt_err = mgmt_status(status);
5774
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005775 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005776 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005777 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005778
5779 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005780 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005781 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005782}
5783
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005784void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5785 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005786{
Johan Hedberg86742e12011-11-07 23:13:38 +02005787 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005788
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005789 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005790
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005791 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005792 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005793 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005794 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005795 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005796 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005797
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005798 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005799}
Johan Hedbergf7520542011-01-20 12:34:39 +02005800
Johan Hedbergd7b25452014-05-23 13:19:53 +03005801static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5802{
5803 if (ltk->authenticated)
5804 return MGMT_LTK_AUTHENTICATED;
5805
5806 return MGMT_LTK_UNAUTHENTICATED;
5807}
5808
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005809void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005810{
5811 struct mgmt_ev_new_long_term_key ev;
5812
5813 memset(&ev, 0, sizeof(ev));
5814
Marcel Holtmann5192d302014-02-19 17:11:58 -08005815 /* Devices using resolvable or non-resolvable random addresses
5816 * without providing an indentity resolving key don't require
5817 * to store long term keys. Their addresses will change the
5818 * next time around.
5819 *
5820 * Only when a remote device provides an identity address
5821 * make sure the long term key is stored. If the remote
5822 * identity is known, the long term keys are internally
5823 * mapped to the identity address. So allow static random
5824 * and public addresses here.
5825 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005826 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5827 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5828 ev.store_hint = 0x00;
5829 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005830 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005831
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005832 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005833 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005834 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005835 ev.key.enc_size = key->enc_size;
5836 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005837 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005838
Johan Hedberg2ceba532014-06-16 19:25:16 +03005839 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005840 ev.key.master = 1;
5841
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005842 memcpy(ev.key.val, key->val, sizeof(key->val));
5843
Marcel Holtmann083368f2013-10-15 14:26:29 -07005844 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005845}
5846
Johan Hedberg95fbac82014-02-19 15:18:31 +02005847void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5848{
5849 struct mgmt_ev_new_irk ev;
5850
5851 memset(&ev, 0, sizeof(ev));
5852
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005853 /* For identity resolving keys from devices that are already
5854 * using a public address or static random address, do not
5855 * ask for storing this key. The identity resolving key really
5856 * is only mandatory for devices using resovlable random
5857 * addresses.
5858 *
5859 * Storing all identity resolving keys has the downside that
5860 * they will be also loaded on next boot of they system. More
5861 * identity resolving keys, means more time during scanning is
5862 * needed to actually resolve these addresses.
5863 */
5864 if (bacmp(&irk->rpa, BDADDR_ANY))
5865 ev.store_hint = 0x01;
5866 else
5867 ev.store_hint = 0x00;
5868
Johan Hedberg95fbac82014-02-19 15:18:31 +02005869 bacpy(&ev.rpa, &irk->rpa);
5870 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5871 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5872 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5873
5874 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5875}
5876
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005877void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5878 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005879{
5880 struct mgmt_ev_new_csrk ev;
5881
5882 memset(&ev, 0, sizeof(ev));
5883
5884 /* Devices using resolvable or non-resolvable random addresses
5885 * without providing an indentity resolving key don't require
5886 * to store signature resolving keys. Their addresses will change
5887 * the next time around.
5888 *
5889 * Only when a remote device provides an identity address
5890 * make sure the signature resolving key is stored. So allow
5891 * static random and public addresses here.
5892 */
5893 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5894 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5895 ev.store_hint = 0x00;
5896 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005897 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005898
5899 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5900 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5901 ev.key.master = csrk->master;
5902 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5903
5904 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5905}
5906
Andre Guedesffb5a8272014-07-01 18:10:11 -03005907void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03005908 u8 bdaddr_type, u8 store_hint, u16 min_interval,
5909 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03005910{
5911 struct mgmt_ev_new_conn_param ev;
5912
Johan Hedbergc103aea2014-07-02 17:37:34 +03005913 if (!hci_is_identity_address(bdaddr, bdaddr_type))
5914 return;
5915
Andre Guedesffb5a8272014-07-01 18:10:11 -03005916 memset(&ev, 0, sizeof(ev));
5917 bacpy(&ev.addr.bdaddr, bdaddr);
5918 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03005919 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03005920 ev.min_interval = cpu_to_le16(min_interval);
5921 ev.max_interval = cpu_to_le16(max_interval);
5922 ev.latency = cpu_to_le16(latency);
5923 ev.timeout = cpu_to_le16(timeout);
5924
5925 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
5926}
5927
Marcel Holtmann94933992013-10-15 10:26:39 -07005928static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5929 u8 data_len)
5930{
5931 eir[eir_len++] = sizeof(type) + data_len;
5932 eir[eir_len++] = type;
5933 memcpy(&eir[eir_len], data, data_len);
5934 eir_len += data_len;
5935
5936 return eir_len;
5937}
5938
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005939void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5940 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5941 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005942{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005943 char buf[512];
5944 struct mgmt_ev_device_connected *ev = (void *) buf;
5945 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005946
Johan Hedbergb644ba32012-01-17 21:48:47 +02005947 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005948 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005949
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005950 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005951
Johan Hedbergb644ba32012-01-17 21:48:47 +02005952 if (name_len > 0)
5953 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005954 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005955
5956 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005957 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005958 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005959
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005960 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005961
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005962 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5963 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005964}
5965
Johan Hedberg8962ee72011-01-20 12:40:27 +02005966static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5967{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005968 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005969 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005970 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005971
Johan Hedberg88c3df12012-02-09 14:27:38 +02005972 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5973 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005974
Johan Hedbergaee9b212012-02-18 15:07:59 +02005975 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005976 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005977
5978 *sk = cmd->sk;
5979 sock_hold(*sk);
5980
Johan Hedberga664b5b2011-02-19 12:06:02 -03005981 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005982}
5983
Johan Hedberg124f6e32012-02-09 13:50:12 +02005984static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005985{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005986 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005987 struct mgmt_cp_unpair_device *cp = cmd->param;
5988 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005989
5990 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005991 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5992 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005993
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005994 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5995
Johan Hedbergaee9b212012-02-18 15:07:59 +02005996 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005997
5998 mgmt_pending_remove(cmd);
5999}
6000
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006001void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006002 u8 link_type, u8 addr_type, u8 reason,
6003 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006004{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006005 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006006 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006007 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006008
Johan Hedberg8b064a32014-02-24 14:52:22 +02006009 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6010 if (power_off) {
6011 struct mgmt_mode *cp = power_off->param;
6012
6013 /* The connection is still in hci_conn_hash so test for 1
6014 * instead of 0 to know if this is the last one.
6015 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006016 if (!cp->val && hci_conn_count(hdev) == 1) {
6017 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006018 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006019 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006020 }
6021
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006022 if (!mgmt_connected)
6023 return;
6024
Andre Guedes57eb7762013-10-30 19:01:41 -03006025 if (link_type != ACL_LINK && link_type != LE_LINK)
6026 return;
6027
Johan Hedberg744cf192011-11-08 20:40:14 +02006028 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006029
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006030 bacpy(&ev.addr.bdaddr, bdaddr);
6031 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6032 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006033
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006034 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006035
6036 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006037 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006038
Johan Hedberg124f6e32012-02-09 13:50:12 +02006039 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006040 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006041}
6042
Marcel Holtmann78929242013-10-06 23:55:47 -07006043void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6044 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006045{
Andre Guedes3655bba2013-10-30 19:01:40 -03006046 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6047 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006048 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006049 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006050
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006051 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6052 hdev);
6053
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006054 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006055 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006056 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006057
Andre Guedes3655bba2013-10-30 19:01:40 -03006058 cp = cmd->param;
6059
6060 if (bacmp(bdaddr, &cp->addr.bdaddr))
6061 return;
6062
6063 if (cp->addr.type != bdaddr_type)
6064 return;
6065
Johan Hedberg88c3df12012-02-09 14:27:38 +02006066 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006067 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006068
Marcel Holtmann78929242013-10-06 23:55:47 -07006069 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6070 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006071
Johan Hedberga664b5b2011-02-19 12:06:02 -03006072 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006073}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006074
Marcel Holtmann445608d2013-10-06 23:55:48 -07006075void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6076 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006077{
6078 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006079 struct pending_cmd *power_off;
6080
6081 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6082 if (power_off) {
6083 struct mgmt_mode *cp = power_off->param;
6084
6085 /* The connection is still in hci_conn_hash so test for 1
6086 * instead of 0 to know if this is the last one.
6087 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006088 if (!cp->val && hci_conn_count(hdev) == 1) {
6089 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006090 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006091 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006092 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006093
Johan Hedberg4c659c32011-11-07 23:13:39 +02006094 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006095 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006096 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006097
Marcel Holtmann445608d2013-10-06 23:55:48 -07006098 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006099}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006100
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006101void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006102{
6103 struct mgmt_ev_pin_code_request ev;
6104
Johan Hedbergd8457692012-02-17 14:24:57 +02006105 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006106 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006107 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006108
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006109 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006110}
6111
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006112void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6113 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006114{
6115 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006116 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006117
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006118 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006119 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006120 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006121
Johan Hedbergd8457692012-02-17 14:24:57 +02006122 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006123 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006124
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006125 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6126 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006127
Johan Hedberga664b5b2011-02-19 12:06:02 -03006128 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006129}
6130
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006131void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6132 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006133{
6134 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006135 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006136
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006137 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006138 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006139 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006140
Johan Hedbergd8457692012-02-17 14:24:57 +02006141 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006142 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006143
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006144 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6145 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006146
Johan Hedberga664b5b2011-02-19 12:06:02 -03006147 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006148}
Johan Hedberga5c29682011-02-19 12:05:57 -03006149
Johan Hedberg744cf192011-11-08 20:40:14 +02006150int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006151 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006152 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006153{
6154 struct mgmt_ev_user_confirm_request ev;
6155
Johan Hedberg744cf192011-11-08 20:40:14 +02006156 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006157
Johan Hedberg272d90d2012-02-09 15:26:12 +02006158 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006159 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006160 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006161 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006162
Johan Hedberg744cf192011-11-08 20:40:14 +02006163 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006164 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006165}
6166
Johan Hedberg272d90d2012-02-09 15:26:12 +02006167int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006168 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006169{
6170 struct mgmt_ev_user_passkey_request ev;
6171
6172 BT_DBG("%s", hdev->name);
6173
Johan Hedberg272d90d2012-02-09 15:26:12 +02006174 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006175 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006176
6177 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006178 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006179}
6180
Brian Gix0df4c182011-11-16 13:53:13 -08006181static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006182 u8 link_type, u8 addr_type, u8 status,
6183 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006184{
6185 struct pending_cmd *cmd;
6186 struct mgmt_rp_user_confirm_reply rp;
6187 int err;
6188
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006189 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006190 if (!cmd)
6191 return -ENOENT;
6192
Johan Hedberg272d90d2012-02-09 15:26:12 +02006193 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006194 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006195 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006196 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006197
Johan Hedberga664b5b2011-02-19 12:06:02 -03006198 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006199
6200 return err;
6201}
6202
Johan Hedberg744cf192011-11-08 20:40:14 +02006203int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006204 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006205{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006206 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006207 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006208}
6209
Johan Hedberg272d90d2012-02-09 15:26:12 +02006210int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006211 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006212{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006213 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006214 status,
6215 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006216}
Johan Hedberg2a611692011-02-19 12:06:00 -03006217
Brian Gix604086b2011-11-23 08:28:33 -08006218int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006219 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006220{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006221 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006222 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006223}
6224
Johan Hedberg272d90d2012-02-09 15:26:12 +02006225int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006226 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006227{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006228 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006229 status,
6230 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006231}
6232
Johan Hedberg92a25252012-09-06 18:39:26 +03006233int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6234 u8 link_type, u8 addr_type, u32 passkey,
6235 u8 entered)
6236{
6237 struct mgmt_ev_passkey_notify ev;
6238
6239 BT_DBG("%s", hdev->name);
6240
6241 bacpy(&ev.addr.bdaddr, bdaddr);
6242 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6243 ev.passkey = __cpu_to_le32(passkey);
6244 ev.entered = entered;
6245
6246 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6247}
6248
Marcel Holtmanne5460992013-10-15 14:26:23 -07006249void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6250 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006251{
6252 struct mgmt_ev_auth_failed ev;
6253
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006254 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006255 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006256 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006257
Marcel Holtmanne5460992013-10-15 14:26:23 -07006258 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006259}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006260
Marcel Holtmann464996a2013-10-15 14:26:24 -07006261void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006262{
6263 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006264 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006265
6266 if (status) {
6267 u8 mgmt_err = mgmt_status(status);
6268 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006269 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006270 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006271 }
6272
Marcel Holtmann464996a2013-10-15 14:26:24 -07006273 if (test_bit(HCI_AUTH, &hdev->flags))
6274 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6275 &hdev->dev_flags);
6276 else
6277 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6278 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006279
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006280 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006281 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006282
Johan Hedberg47990ea2012-02-22 11:58:37 +02006283 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006284 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006285
6286 if (match.sk)
6287 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006288}
6289
Johan Hedberg890ea892013-03-15 17:06:52 -05006290static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006291{
Johan Hedberg890ea892013-03-15 17:06:52 -05006292 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006293 struct hci_cp_write_eir cp;
6294
Johan Hedberg976eb202012-10-24 21:12:01 +03006295 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006296 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006297
Johan Hedbergc80da272012-02-22 15:38:48 +02006298 memset(hdev->eir, 0, sizeof(hdev->eir));
6299
Johan Hedbergcacaf522012-02-21 00:52:42 +02006300 memset(&cp, 0, sizeof(cp));
6301
Johan Hedberg890ea892013-03-15 17:06:52 -05006302 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006303}
6304
Marcel Holtmann3e248562013-10-15 14:26:25 -07006305void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006306{
6307 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006308 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006309 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006310
6311 if (status) {
6312 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006313
6314 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006315 &hdev->dev_flags)) {
6316 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006317 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006318 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006319
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006320 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6321 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006322 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006323 }
6324
6325 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006326 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006327 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006328 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6329 if (!changed)
6330 changed = test_and_clear_bit(HCI_HS_ENABLED,
6331 &hdev->dev_flags);
6332 else
6333 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006334 }
6335
6336 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6337
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006338 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006339 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006340
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006341 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006342 sock_put(match.sk);
6343
Johan Hedberg890ea892013-03-15 17:06:52 -05006344 hci_req_init(&req, hdev);
6345
Johan Hedberg37699722014-06-24 14:00:27 +03006346 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6347 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6348 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6349 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006350 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006351 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006352 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006353 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006354
6355 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006356}
6357
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006358void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6359{
6360 struct cmd_lookup match = { NULL, hdev };
6361 bool changed = false;
6362
6363 if (status) {
6364 u8 mgmt_err = mgmt_status(status);
6365
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006366 if (enable) {
6367 if (test_and_clear_bit(HCI_SC_ENABLED,
6368 &hdev->dev_flags))
6369 new_settings(hdev, NULL);
6370 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6371 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006372
6373 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6374 cmd_status_rsp, &mgmt_err);
6375 return;
6376 }
6377
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006378 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006379 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006380 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006381 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006382 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6383 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006384
6385 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6386 settings_rsp, &match);
6387
6388 if (changed)
6389 new_settings(hdev, match.sk);
6390
6391 if (match.sk)
6392 sock_put(match.sk);
6393}
6394
Johan Hedberg92da6092013-03-15 17:06:55 -05006395static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006396{
6397 struct cmd_lookup *match = data;
6398
Johan Hedberg90e70452012-02-23 23:09:40 +02006399 if (match->sk == NULL) {
6400 match->sk = cmd->sk;
6401 sock_hold(match->sk);
6402 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006403}
6404
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006405void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6406 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006407{
Johan Hedberg90e70452012-02-23 23:09:40 +02006408 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006409
Johan Hedberg92da6092013-03-15 17:06:55 -05006410 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6411 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6412 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006413
6414 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006415 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6416 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006417
6418 if (match.sk)
6419 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006420}
6421
Marcel Holtmann7667da32013-10-15 14:26:27 -07006422void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006423{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006424 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006425 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006426
Johan Hedberg13928972013-03-15 17:07:00 -05006427 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006428 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006429
6430 memset(&ev, 0, sizeof(ev));
6431 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006432 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006433
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006434 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006435 if (!cmd) {
6436 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006437
Johan Hedberg13928972013-03-15 17:07:00 -05006438 /* If this is a HCI command related to powering on the
6439 * HCI dev don't send any mgmt signals.
6440 */
6441 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006442 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006443 }
6444
Marcel Holtmann7667da32013-10-15 14:26:27 -07006445 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6446 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006447}
Szymon Jancc35938b2011-03-22 13:12:21 +01006448
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006449void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6450 u8 *randomizer192, u8 *hash256,
6451 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006452{
6453 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006454
Johan Hedberg744cf192011-11-08 20:40:14 +02006455 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006456
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006457 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006458 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006459 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006460
6461 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006462 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6463 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006464 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006465 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6466 hash256 && randomizer256) {
6467 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006468
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006469 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6470 memcpy(rp.randomizer192, randomizer192,
6471 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006472
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006473 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6474 memcpy(rp.randomizer256, randomizer256,
6475 sizeof(rp.randomizer256));
6476
6477 cmd_complete(cmd->sk, hdev->id,
6478 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6479 &rp, sizeof(rp));
6480 } else {
6481 struct mgmt_rp_read_local_oob_data rp;
6482
6483 memcpy(rp.hash, hash192, sizeof(rp.hash));
6484 memcpy(rp.randomizer, randomizer192,
6485 sizeof(rp.randomizer));
6486
6487 cmd_complete(cmd->sk, hdev->id,
6488 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6489 &rp, sizeof(rp));
6490 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006491 }
6492
6493 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006494}
Johan Hedberge17acd42011-03-30 23:57:16 +03006495
Marcel Holtmann901801b2013-10-06 23:55:51 -07006496void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006497 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6498 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006499{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006500 char buf[512];
6501 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006502 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006503 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006504
Johan Hedberg75ce2082014-07-02 22:42:01 +03006505 /* Don't send events for a non-kernel initiated discovery. With
6506 * LE one exception is if we have pend_le_reports > 0 in which
6507 * case we're doing passive scanning and want these events.
6508 */
6509 if (!hci_discovery_active(hdev)) {
6510 if (link_type == ACL_LINK)
6511 return;
6512 if (link_type == LE_LINK && !hdev->pend_le_reports)
6513 return;
6514 }
Andre Guedes12602d02013-04-30 15:29:40 -03006515
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006516 /* Make sure that the buffer is big enough. The 5 extra bytes
6517 * are for the potential CoD field.
6518 */
6519 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006520 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006521
Johan Hedberg1dc06092012-01-15 21:01:23 +02006522 memset(buf, 0, sizeof(buf));
6523
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006524 irk = hci_get_irk(hdev, bdaddr, addr_type);
6525 if (irk) {
6526 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6527 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6528 } else {
6529 bacpy(&ev->addr.bdaddr, bdaddr);
6530 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6531 }
6532
Johan Hedberge319d2e2012-01-15 19:51:59 +02006533 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006534 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006535
Johan Hedberg1dc06092012-01-15 21:01:23 +02006536 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006537 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006538
Johan Hedberg1dc06092012-01-15 21:01:23 +02006539 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6540 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006541 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006542
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006543 if (scan_rsp_len > 0)
6544 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6545
6546 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6547 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006548
Marcel Holtmann901801b2013-10-06 23:55:51 -07006549 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006550}
Johan Hedberga88a9652011-03-30 13:18:12 +03006551
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006552void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6553 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006554{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006555 struct mgmt_ev_device_found *ev;
6556 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6557 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006558
Johan Hedbergb644ba32012-01-17 21:48:47 +02006559 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006560
Johan Hedbergb644ba32012-01-17 21:48:47 +02006561 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006562
Johan Hedbergb644ba32012-01-17 21:48:47 +02006563 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006564 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006565 ev->rssi = rssi;
6566
6567 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006568 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006569
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006570 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006571
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006572 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006573}
Johan Hedberg314b2382011-04-27 10:29:57 -04006574
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006575void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006576{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006577 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006578 struct pending_cmd *cmd;
6579
Andre Guedes343fb142011-11-22 17:14:19 -03006580 BT_DBG("%s discovering %u", hdev->name, discovering);
6581
Johan Hedberg164a6e72011-11-01 17:06:44 +02006582 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006583 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006584 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006585 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006586
6587 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006588 u8 type = hdev->discovery.type;
6589
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006590 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6591 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006592 mgmt_pending_remove(cmd);
6593 }
6594
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006595 memset(&ev, 0, sizeof(ev));
6596 ev.type = hdev->discovery.type;
6597 ev.discovering = discovering;
6598
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006599 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006600}
Antti Julku5e762442011-08-25 16:48:02 +03006601
Marcel Holtmann5976e602013-10-06 04:08:14 -07006602static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6603{
6604 BT_DBG("%s status %u", hdev->name, status);
6605
6606 /* Clear the advertising mgmt setting if we failed to re-enable it */
6607 if (status) {
6608 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006609 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006610 }
6611}
6612
6613void mgmt_reenable_advertising(struct hci_dev *hdev)
6614{
6615 struct hci_request req;
6616
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006617 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006618 return;
6619
6620 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6621 return;
6622
6623 hci_req_init(&req, hdev);
6624 enable_advertising(&req);
6625
6626 /* If this fails we have no option but to let user space know
6627 * that we've disabled advertising.
6628 */
6629 if (hci_req_run(&req, adv_enable_complete) < 0) {
6630 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006631 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006632 }
6633}