blob: 747746b0d2c438db059e1093b8ceadf9f17e3e1e [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 Holtmannb75cf9c2014-05-09 04:18:42 -070038#define MGMT_REVISION 6
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 Hedberge70bb2e2012-02-13 16:59:33 +020088};
89
90static const u16 mgmt_events[] = {
91 MGMT_EV_CONTROLLER_ERROR,
92 MGMT_EV_INDEX_ADDED,
93 MGMT_EV_INDEX_REMOVED,
94 MGMT_EV_NEW_SETTINGS,
95 MGMT_EV_CLASS_OF_DEV_CHANGED,
96 MGMT_EV_LOCAL_NAME_CHANGED,
97 MGMT_EV_NEW_LINK_KEY,
98 MGMT_EV_NEW_LONG_TERM_KEY,
99 MGMT_EV_DEVICE_CONNECTED,
100 MGMT_EV_DEVICE_DISCONNECTED,
101 MGMT_EV_CONNECT_FAILED,
102 MGMT_EV_PIN_CODE_REQUEST,
103 MGMT_EV_USER_CONFIRM_REQUEST,
104 MGMT_EV_USER_PASSKEY_REQUEST,
105 MGMT_EV_AUTH_FAILED,
106 MGMT_EV_DEVICE_FOUND,
107 MGMT_EV_DISCOVERING,
108 MGMT_EV_DEVICE_BLOCKED,
109 MGMT_EV_DEVICE_UNBLOCKED,
110 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300111 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800112 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700113 MGMT_EV_NEW_CSRK,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200114};
115
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800116#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200117
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200118#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
119 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
120
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200121struct pending_cmd {
122 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200123 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200124 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100125 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200126 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300127 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200128};
129
Johan Hedbergca69b792011-11-11 18:10:00 +0200130/* HCI to MGMT error code conversion table */
131static u8 mgmt_status_table[] = {
132 MGMT_STATUS_SUCCESS,
133 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
134 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
135 MGMT_STATUS_FAILED, /* Hardware Failure */
136 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
137 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200138 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200139 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
140 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
141 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
142 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
143 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
144 MGMT_STATUS_BUSY, /* Command Disallowed */
145 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
146 MGMT_STATUS_REJECTED, /* Rejected Security */
147 MGMT_STATUS_REJECTED, /* Rejected Personal */
148 MGMT_STATUS_TIMEOUT, /* Host Timeout */
149 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
150 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
151 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
152 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
153 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
154 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
155 MGMT_STATUS_BUSY, /* Repeated Attempts */
156 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
157 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
158 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
159 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
160 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
161 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
162 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
163 MGMT_STATUS_FAILED, /* Unspecified Error */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
165 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
166 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
167 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
168 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
169 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
170 MGMT_STATUS_FAILED, /* Unit Link Key Used */
171 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
172 MGMT_STATUS_TIMEOUT, /* Instant Passed */
173 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
174 MGMT_STATUS_FAILED, /* Transaction Collision */
175 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
176 MGMT_STATUS_REJECTED, /* QoS Rejected */
177 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
178 MGMT_STATUS_REJECTED, /* Insufficient Security */
179 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
180 MGMT_STATUS_BUSY, /* Role Switch Pending */
181 MGMT_STATUS_FAILED, /* Slot Violation */
182 MGMT_STATUS_FAILED, /* Role Switch Failed */
183 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
184 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
185 MGMT_STATUS_BUSY, /* Host Busy Pairing */
186 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
187 MGMT_STATUS_BUSY, /* Controller Busy */
188 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
189 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
190 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
191 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
192 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
193};
194
195static u8 mgmt_status(u8 hci_status)
196{
197 if (hci_status < ARRAY_SIZE(mgmt_status_table))
198 return mgmt_status_table[hci_status];
199
200 return MGMT_STATUS_FAILED;
201}
202
Szymon Janc4e51eae2011-02-25 19:05:48 +0100203static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200204{
205 struct sk_buff *skb;
206 struct mgmt_hdr *hdr;
207 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300208 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200209
Szymon Janc34eb5252011-02-28 14:10:08 +0100210 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200211
Andre Guedes790eff42012-06-07 19:05:46 -0300212 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200213 if (!skb)
214 return -ENOMEM;
215
216 hdr = (void *) skb_put(skb, sizeof(*hdr));
217
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700218 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100219 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200220 hdr->len = cpu_to_le16(sizeof(*ev));
221
222 ev = (void *) skb_put(skb, sizeof(*ev));
223 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200224 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200225
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300226 err = sock_queue_rcv_skb(sk, skb);
227 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200228 kfree_skb(skb);
229
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300230 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200231}
232
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200233static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300234 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200235{
236 struct sk_buff *skb;
237 struct mgmt_hdr *hdr;
238 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300239 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200240
241 BT_DBG("sock %p", sk);
242
Andre Guedes790eff42012-06-07 19:05:46 -0300243 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200244 if (!skb)
245 return -ENOMEM;
246
247 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200248
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700249 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100250 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200251 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200252
Johan Hedberga38528f2011-01-22 06:46:43 +0200253 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200254 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200255 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100256
257 if (rp)
258 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200259
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300260 err = sock_queue_rcv_skb(sk, skb);
261 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200262 kfree_skb(skb);
263
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100264 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200265}
266
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300267static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
268 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200269{
270 struct mgmt_rp_read_version rp;
271
272 BT_DBG("sock %p", sk);
273
274 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700275 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200279}
280
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300281static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
282 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200283{
284 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200285 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
286 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200287 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200288 size_t rp_size;
289 int i, err;
290
291 BT_DBG("sock %p", sk);
292
293 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
294
295 rp = kmalloc(rp_size, GFP_KERNEL);
296 if (!rp)
297 return -ENOMEM;
298
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700299 rp->num_commands = cpu_to_le16(num_commands);
300 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200301
302 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
303 put_unaligned_le16(mgmt_commands[i], opcode);
304
305 for (i = 0; i < num_events; i++, opcode++)
306 put_unaligned_le16(mgmt_events[i], opcode);
307
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200308 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300309 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200310 kfree(rp);
311
312 return err;
313}
314
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300315static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
316 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200317{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200318 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200319 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200320 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200321 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300322 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200323
324 BT_DBG("sock %p", sk);
325
326 read_lock(&hci_dev_list_lock);
327
328 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300329 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700330 if (d->dev_type == HCI_BREDR)
331 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200332 }
333
Johan Hedberga38528f2011-01-22 06:46:43 +0200334 rp_len = sizeof(*rp) + (2 * count);
335 rp = kmalloc(rp_len, GFP_ATOMIC);
336 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100337 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200338 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100339 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200340
Johan Hedberg476e44c2012-10-19 20:10:46 +0300341 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200342 list_for_each_entry(d, &hci_dev_list, list) {
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200343 if (test_bit(HCI_SETUP, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200344 continue;
345
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700346 if (test_bit(HCI_USER_CHANNEL, &d->dev_flags))
347 continue;
348
Marcel Holtmann1514b892013-10-06 08:25:01 -0700349 if (d->dev_type == HCI_BREDR) {
350 rp->index[count++] = cpu_to_le16(d->id);
351 BT_DBG("Added hci%u", d->id);
352 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200353 }
354
Johan Hedberg476e44c2012-10-19 20:10:46 +0300355 rp->num_controllers = cpu_to_le16(count);
356 rp_len = sizeof(*rp) + (2 * count);
357
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200358 read_unlock(&hci_dev_list_lock);
359
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200360 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300361 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362
Johan Hedberga38528f2011-01-22 06:46:43 +0200363 kfree(rp);
364
365 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366}
367
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200368static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200369{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200370 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200371
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200372 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200373 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800374 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200375
Andre Guedesed3fa312012-07-24 15:03:46 -0300376 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300377 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500378 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
379 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300380 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200381 settings |= MGMT_SETTING_BREDR;
382 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700383
384 if (lmp_ssp_capable(hdev)) {
385 settings |= MGMT_SETTING_SSP;
386 settings |= MGMT_SETTING_HS;
387 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800388
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800389 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200390 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800391 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700392 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100393
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300394 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200395 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300396 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200397 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300398 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200399
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200400 return settings;
401}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200402
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200403static u32 get_current_settings(struct hci_dev *hdev)
404{
405 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200406
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200407 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100408 settings |= MGMT_SETTING_POWERED;
409
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200410 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200411 settings |= MGMT_SETTING_CONNECTABLE;
412
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500413 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
414 settings |= MGMT_SETTING_FAST_CONNECTABLE;
415
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200416 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200417 settings |= MGMT_SETTING_DISCOVERABLE;
418
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200419 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200420 settings |= MGMT_SETTING_PAIRABLE;
421
Johan Hedberg56f87902013-10-02 13:43:13 +0300422 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200423 settings |= MGMT_SETTING_BREDR;
424
Johan Hedberg06199cf2012-02-22 16:37:11 +0200425 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200426 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200427
Johan Hedberg47990ea2012-02-22 11:58:37 +0200428 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200429 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200430
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200431 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200432 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200433
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200434 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
435 settings |= MGMT_SETTING_HS;
436
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200437 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300438 settings |= MGMT_SETTING_ADVERTISING;
439
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800440 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
441 settings |= MGMT_SETTING_SECURE_CONN;
442
Johan Hedberg0663b292014-06-24 13:15:50 +0300443 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800444 settings |= MGMT_SETTING_DEBUG_KEYS;
445
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200446 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
447 settings |= MGMT_SETTING_PRIVACY;
448
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200449 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200450}
451
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300452#define PNP_INFO_SVCLASS_ID 0x1200
453
Johan Hedberg213202e2013-01-27 00:31:33 +0200454static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
455{
456 u8 *ptr = data, *uuids_start = NULL;
457 struct bt_uuid *uuid;
458
459 if (len < 4)
460 return ptr;
461
462 list_for_each_entry(uuid, &hdev->uuids, list) {
463 u16 uuid16;
464
465 if (uuid->size != 16)
466 continue;
467
468 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
469 if (uuid16 < 0x1100)
470 continue;
471
472 if (uuid16 == PNP_INFO_SVCLASS_ID)
473 continue;
474
475 if (!uuids_start) {
476 uuids_start = ptr;
477 uuids_start[0] = 1;
478 uuids_start[1] = EIR_UUID16_ALL;
479 ptr += 2;
480 }
481
482 /* Stop if not enough space to put next UUID */
483 if ((ptr - data) + sizeof(u16) > len) {
484 uuids_start[1] = EIR_UUID16_SOME;
485 break;
486 }
487
488 *ptr++ = (uuid16 & 0x00ff);
489 *ptr++ = (uuid16 & 0xff00) >> 8;
490 uuids_start[0] += sizeof(uuid16);
491 }
492
493 return ptr;
494}
495
Johan Hedbergcdf19632013-01-27 00:31:34 +0200496static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
497{
498 u8 *ptr = data, *uuids_start = NULL;
499 struct bt_uuid *uuid;
500
501 if (len < 6)
502 return ptr;
503
504 list_for_each_entry(uuid, &hdev->uuids, list) {
505 if (uuid->size != 32)
506 continue;
507
508 if (!uuids_start) {
509 uuids_start = ptr;
510 uuids_start[0] = 1;
511 uuids_start[1] = EIR_UUID32_ALL;
512 ptr += 2;
513 }
514
515 /* Stop if not enough space to put next UUID */
516 if ((ptr - data) + sizeof(u32) > len) {
517 uuids_start[1] = EIR_UUID32_SOME;
518 break;
519 }
520
521 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
522 ptr += sizeof(u32);
523 uuids_start[0] += sizeof(u32);
524 }
525
526 return ptr;
527}
528
Johan Hedbergc00d5752013-01-27 00:31:35 +0200529static u8 *create_uuid128_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 < 18)
535 return ptr;
536
537 list_for_each_entry(uuid, &hdev->uuids, list) {
538 if (uuid->size != 128)
539 continue;
540
541 if (!uuids_start) {
542 uuids_start = ptr;
543 uuids_start[0] = 1;
544 uuids_start[1] = EIR_UUID128_ALL;
545 ptr += 2;
546 }
547
548 /* Stop if not enough space to put next UUID */
549 if ((ptr - data) + 16 > len) {
550 uuids_start[1] = EIR_UUID128_SOME;
551 break;
552 }
553
554 memcpy(ptr, uuid->uuid, 16);
555 ptr += 16;
556 uuids_start[0] += 16;
557 }
558
559 return ptr;
560}
561
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300562static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
563{
564 struct pending_cmd *cmd;
565
566 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
567 if (cmd->opcode == opcode)
568 return cmd;
569 }
570
571 return NULL;
572}
573
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700574static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
575{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700576 u8 ad_len = 0;
577 size_t name_len;
578
579 name_len = strlen(hdev->dev_name);
580 if (name_len > 0) {
581 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
582
583 if (name_len > max_len) {
584 name_len = max_len;
585 ptr[1] = EIR_NAME_SHORT;
586 } else
587 ptr[1] = EIR_NAME_COMPLETE;
588
589 ptr[0] = name_len + 1;
590
591 memcpy(ptr + 2, hdev->dev_name, name_len);
592
593 ad_len += (name_len + 2);
594 ptr += (name_len + 2);
595 }
596
597 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700598}
599
600static void update_scan_rsp_data(struct hci_request *req)
601{
602 struct hci_dev *hdev = req->hdev;
603 struct hci_cp_le_set_scan_rsp_data cp;
604 u8 len;
605
Johan Hedberg7751ef12013-10-19 23:38:15 +0300606 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700607 return;
608
609 memset(&cp, 0, sizeof(cp));
610
611 len = create_scan_rsp_data(hdev, cp.data);
612
Johan Hedbergeb438b52013-10-16 15:31:07 +0300613 if (hdev->scan_rsp_data_len == len &&
614 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700615 return;
616
Johan Hedbergeb438b52013-10-16 15:31:07 +0300617 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
618 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700619
620 cp.length = len;
621
622 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
623}
624
Johan Hedberg9a43e252013-10-20 19:00:07 +0300625static u8 get_adv_discov_flags(struct hci_dev *hdev)
626{
627 struct pending_cmd *cmd;
628
629 /* If there's a pending mgmt command the flags will not yet have
630 * their final values, so check for this first.
631 */
632 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
633 if (cmd) {
634 struct mgmt_mode *cp = cmd->param;
635 if (cp->val == 0x01)
636 return LE_AD_GENERAL;
637 else if (cp->val == 0x02)
638 return LE_AD_LIMITED;
639 } else {
640 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
641 return LE_AD_LIMITED;
642 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
643 return LE_AD_GENERAL;
644 }
645
646 return 0;
647}
648
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700649static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700650{
651 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700652
Johan Hedberg9a43e252013-10-20 19:00:07 +0300653 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700654
Johan Hedberge8340042014-01-30 11:16:50 -0800655 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700656 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700657
658 if (flags) {
659 BT_DBG("adv flags 0x%02x", flags);
660
661 ptr[0] = 2;
662 ptr[1] = EIR_FLAGS;
663 ptr[2] = flags;
664
665 ad_len += 3;
666 ptr += 3;
667 }
668
669 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
670 ptr[0] = 2;
671 ptr[1] = EIR_TX_POWER;
672 ptr[2] = (u8) hdev->adv_tx_power;
673
674 ad_len += 3;
675 ptr += 3;
676 }
677
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700678 return ad_len;
679}
680
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700681static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700682{
683 struct hci_dev *hdev = req->hdev;
684 struct hci_cp_le_set_adv_data cp;
685 u8 len;
686
Johan Hedberg10994ce2013-10-19 23:38:16 +0300687 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700688 return;
689
690 memset(&cp, 0, sizeof(cp));
691
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700692 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700693
694 if (hdev->adv_data_len == len &&
695 memcmp(cp.data, hdev->adv_data, len) == 0)
696 return;
697
698 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
699 hdev->adv_data_len = len;
700
701 cp.length = len;
702
703 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
704}
705
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300706static void create_eir(struct hci_dev *hdev, u8 *data)
707{
708 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300709 size_t name_len;
710
711 name_len = strlen(hdev->dev_name);
712
713 if (name_len > 0) {
714 /* EIR Data type */
715 if (name_len > 48) {
716 name_len = 48;
717 ptr[1] = EIR_NAME_SHORT;
718 } else
719 ptr[1] = EIR_NAME_COMPLETE;
720
721 /* EIR Data length */
722 ptr[0] = name_len + 1;
723
724 memcpy(ptr + 2, hdev->dev_name, name_len);
725
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300726 ptr += (name_len + 2);
727 }
728
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100729 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700730 ptr[0] = 2;
731 ptr[1] = EIR_TX_POWER;
732 ptr[2] = (u8) hdev->inq_tx_power;
733
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700734 ptr += 3;
735 }
736
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700737 if (hdev->devid_source > 0) {
738 ptr[0] = 9;
739 ptr[1] = EIR_DEVICE_ID;
740
741 put_unaligned_le16(hdev->devid_source, ptr + 2);
742 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
743 put_unaligned_le16(hdev->devid_product, ptr + 6);
744 put_unaligned_le16(hdev->devid_version, ptr + 8);
745
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700746 ptr += 10;
747 }
748
Johan Hedberg213202e2013-01-27 00:31:33 +0200749 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200750 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200751 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300752}
753
Johan Hedberg890ea892013-03-15 17:06:52 -0500754static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300755{
Johan Hedberg890ea892013-03-15 17:06:52 -0500756 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300757 struct hci_cp_write_eir cp;
758
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200759 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500760 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200761
Johan Hedberg976eb202012-10-24 21:12:01 +0300762 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500763 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300764
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200765 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500766 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300767
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200768 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500769 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300770
771 memset(&cp, 0, sizeof(cp));
772
773 create_eir(hdev, cp.data);
774
775 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500776 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300777
778 memcpy(hdev->eir, cp.data, sizeof(cp.data));
779
Johan Hedberg890ea892013-03-15 17:06:52 -0500780 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300781}
782
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200783static u8 get_service_classes(struct hci_dev *hdev)
784{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300785 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200786 u8 val = 0;
787
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300788 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200789 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200790
791 return val;
792}
793
Johan Hedberg890ea892013-03-15 17:06:52 -0500794static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200795{
Johan Hedberg890ea892013-03-15 17:06:52 -0500796 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200797 u8 cod[3];
798
799 BT_DBG("%s", hdev->name);
800
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200801 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500802 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200803
Johan Hedbergf87ea1d2013-10-19 23:38:17 +0300804 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
805 return;
806
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200807 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500808 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200809
810 cod[0] = hdev->minor_class;
811 cod[1] = hdev->major_class;
812 cod[2] = get_service_classes(hdev);
813
Marcel Holtmann6acd7db2013-10-15 06:33:53 -0700814 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
815 cod[1] |= 0x20;
816
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200817 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500818 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200819
Johan Hedberg890ea892013-03-15 17:06:52 -0500820 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200821}
822
Johan Hedberga4858cb2014-02-25 19:56:31 +0200823static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200824{
825 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200826
827 /* If there's a pending mgmt command the flag will not yet have
828 * it's final value, so check for this first.
829 */
830 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
831 if (cmd) {
832 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200833 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200834 }
835
Johan Hedberga4858cb2014-02-25 19:56:31 +0200836 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200837}
838
839static void enable_advertising(struct hci_request *req)
840{
841 struct hci_dev *hdev = req->hdev;
842 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200843 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +0200844 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200845
Johan Hedberg8d972502014-02-28 12:54:14 +0200846 /* Clear the HCI_ADVERTISING bit temporarily so that the
847 * hci_update_random_address knows that it's safe to go ahead
848 * and write a new random address. The flag will be set back on
849 * as soon as the SET_ADV_ENABLE HCI command completes.
850 */
851 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
852
Johan Hedberga4858cb2014-02-25 19:56:31 +0200853 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200854
Johan Hedberga4858cb2014-02-25 19:56:31 +0200855 /* Set require_privacy to true only when non-connectable
856 * advertising is used. In that case it is fine to use a
857 * non-resolvable private address.
858 */
859 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200860 return;
861
Marcel Holtmann41c90c12014-02-23 20:25:55 -0800862 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700863 cp.min_interval = cpu_to_le16(0x0800);
864 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +0200865 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +0200866 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +0200867 cp.channel_map = hdev->le_adv_channel_map;
868
869 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
870
871 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
872}
873
874static void disable_advertising(struct hci_request *req)
875{
876 u8 enable = 0x00;
877
878 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
879}
880
Johan Hedberg7d785252011-12-15 00:47:39 +0200881static void service_cache_off(struct work_struct *work)
882{
883 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300884 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -0500885 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +0200886
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200887 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +0200888 return;
889
Johan Hedberg890ea892013-03-15 17:06:52 -0500890 hci_req_init(&req, hdev);
891
Johan Hedberg7d785252011-12-15 00:47:39 +0200892 hci_dev_lock(hdev);
893
Johan Hedberg890ea892013-03-15 17:06:52 -0500894 update_eir(&req);
895 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +0200896
897 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -0500898
899 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +0200900}
901
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200902static void rpa_expired(struct work_struct *work)
903{
904 struct hci_dev *hdev = container_of(work, struct hci_dev,
905 rpa_expired.work);
906 struct hci_request req;
907
908 BT_DBG("");
909
910 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
911
912 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
913 hci_conn_num(hdev, LE_LINK) > 0)
914 return;
915
916 /* The generation of a new RPA and programming it into the
917 * controller happens in the enable_advertising() function.
918 */
919
920 hci_req_init(&req, hdev);
921
922 disable_advertising(&req);
923 enable_advertising(&req);
924
925 hci_req_run(&req, NULL);
926}
927
Johan Hedberg6a919082012-02-28 06:17:26 +0200928static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +0200929{
Johan Hedberg4f87da82012-03-02 19:55:56 +0200930 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +0200931 return;
932
Johan Hedberg4f87da82012-03-02 19:55:56 +0200933 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +0200934 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +0200935
Johan Hedberg4f87da82012-03-02 19:55:56 +0200936 /* Non-mgmt controlled devices get this bit set
937 * implicitly so that pairing works for them, however
938 * for mgmt we require user-space to explicitly enable
939 * it
940 */
941 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +0200942}
943
Johan Hedberg0f4e68c2012-02-28 17:18:30 +0200944static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300945 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +0200946{
947 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +0200948
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200949 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +0200950
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300951 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200952
Johan Hedberg03811012010-12-08 00:21:06 +0200953 memset(&rp, 0, sizeof(rp));
954
Johan Hedberg03811012010-12-08 00:21:06 +0200955 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200956
957 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200958 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200959
960 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
961 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
962
963 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +0200964
965 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +0200966 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +0200967
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300968 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +0200969
Johan Hedbergbdb6d972012-02-28 06:13:32 +0200970 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300971 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +0200972}
973
974static void mgmt_pending_free(struct pending_cmd *cmd)
975{
976 sock_put(cmd->sk);
977 kfree(cmd->param);
978 kfree(cmd);
979}
980
981static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300982 struct hci_dev *hdev, void *data,
983 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +0200984{
985 struct pending_cmd *cmd;
986
Andre Guedes12b94562012-06-07 19:05:45 -0300987 cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200988 if (!cmd)
989 return NULL;
990
991 cmd->opcode = opcode;
992 cmd->index = hdev->id;
993
Andre Guedes12b94562012-06-07 19:05:45 -0300994 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +0200995 if (!cmd->param) {
996 kfree(cmd);
997 return NULL;
998 }
999
1000 if (data)
1001 memcpy(cmd->param, data, len);
1002
1003 cmd->sk = sk;
1004 sock_hold(sk);
1005
1006 list_add(&cmd->list, &hdev->mgmt_pending);
1007
1008 return cmd;
1009}
1010
1011static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001012 void (*cb)(struct pending_cmd *cmd,
1013 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001014 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001015{
Andre Guedesa3d09352013-02-01 11:21:30 -03001016 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001017
Andre Guedesa3d09352013-02-01 11:21:30 -03001018 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001019 if (opcode > 0 && cmd->opcode != opcode)
1020 continue;
1021
1022 cb(cmd, data);
1023 }
1024}
1025
Johan Hedberg03811012010-12-08 00:21:06 +02001026static void mgmt_pending_remove(struct pending_cmd *cmd)
1027{
1028 list_del(&cmd->list);
1029 mgmt_pending_free(cmd);
1030}
1031
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001032static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001033{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001034 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001035
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001036 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001037 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001038}
1039
Johan Hedberg8b064a32014-02-24 14:52:22 +02001040static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1041{
1042 BT_DBG("%s status 0x%02x", hdev->name, status);
1043
Johan Hedberga3172b72014-02-28 09:33:44 +02001044 if (hci_conn_count(hdev) == 0) {
1045 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001046 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001047 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001048}
1049
Johan Hedberg21a60d32014-06-10 14:05:58 +03001050static void hci_stop_discovery(struct hci_request *req)
1051{
1052 struct hci_dev *hdev = req->hdev;
1053 struct hci_cp_remote_name_req_cancel cp;
1054 struct inquiry_entry *e;
1055
1056 switch (hdev->discovery.state) {
1057 case DISCOVERY_FINDING:
1058 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1059 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1060 } else {
1061 cancel_delayed_work(&hdev->le_scan_disable);
1062 hci_req_add_le_scan_disable(req);
1063 }
1064
1065 break;
1066
1067 case DISCOVERY_RESOLVING:
1068 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1069 NAME_PENDING);
1070 if (!e)
1071 return;
1072
1073 bacpy(&cp.bdaddr, &e->data.bdaddr);
1074 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1075 &cp);
1076
1077 break;
1078
1079 default:
1080 /* Passive scanning */
1081 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1082 hci_req_add_le_scan_disable(req);
1083 break;
1084 }
1085}
1086
Johan Hedberg8b064a32014-02-24 14:52:22 +02001087static int clean_up_hci_state(struct hci_dev *hdev)
1088{
1089 struct hci_request req;
1090 struct hci_conn *conn;
1091
1092 hci_req_init(&req, hdev);
1093
1094 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1095 test_bit(HCI_PSCAN, &hdev->flags)) {
1096 u8 scan = 0x00;
1097 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1098 }
1099
1100 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1101 disable_advertising(&req);
1102
Johan Hedbergf8680f12014-06-10 14:05:59 +03001103 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001104
1105 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1106 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001107 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001108
Johan Hedbergc9910d02014-02-27 14:35:12 +02001109 switch (conn->state) {
1110 case BT_CONNECTED:
1111 case BT_CONFIG:
1112 dc.handle = cpu_to_le16(conn->handle);
1113 dc.reason = 0x15; /* Terminated due to Power Off */
1114 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1115 break;
1116 case BT_CONNECT:
1117 if (conn->type == LE_LINK)
1118 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1119 0, NULL);
1120 else if (conn->type == ACL_LINK)
1121 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1122 6, &conn->dst);
1123 break;
1124 case BT_CONNECT2:
1125 bacpy(&rej.bdaddr, &conn->dst);
1126 rej.reason = 0x15; /* Terminated due to Power Off */
1127 if (conn->type == ACL_LINK)
1128 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1129 sizeof(rej), &rej);
1130 else if (conn->type == SCO_LINK)
1131 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1132 sizeof(rej), &rej);
1133 break;
1134 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001135 }
1136
1137 return hci_req_run(&req, clean_up_hci_complete);
1138}
1139
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001140static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001141 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001142{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001143 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001144 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001145 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001147 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Johan Hedberga7e80f22013-01-09 16:05:19 +02001149 if (cp->val != 0x00 && cp->val != 0x01)
1150 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1151 MGMT_STATUS_INVALID_PARAMS);
1152
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001153 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001154
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001155 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1156 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1157 MGMT_STATUS_BUSY);
1158 goto failed;
1159 }
1160
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001161 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1162 cancel_delayed_work(&hdev->power_off);
1163
1164 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001165 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1166 data, len);
1167 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001168 goto failed;
1169 }
1170 }
1171
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001172 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001174 goto failed;
1175 }
1176
Johan Hedberg03811012010-12-08 00:21:06 +02001177 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1178 if (!cmd) {
1179 err = -ENOMEM;
1180 goto failed;
1181 }
1182
Johan Hedberg8b064a32014-02-24 14:52:22 +02001183 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001184 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001185 err = 0;
1186 } else {
1187 /* Disconnect connections, stop scans, etc */
1188 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001189 if (!err)
1190 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1191 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001192
Johan Hedberg8b064a32014-02-24 14:52:22 +02001193 /* ENODATA means there were no HCI commands queued */
1194 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001195 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001196 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1197 err = 0;
1198 }
1199 }
Johan Hedberg03811012010-12-08 00:21:06 +02001200
1201failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001202 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 return err;
1204}
1205
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001206static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
1207 struct sock *skip_sk)
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001208{
1209 struct sk_buff *skb;
1210 struct mgmt_hdr *hdr;
1211
Andre Guedes790eff42012-06-07 19:05:46 -03001212 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001213 if (!skb)
1214 return -ENOMEM;
1215
1216 hdr = (void *) skb_put(skb, sizeof(*hdr));
1217 hdr->opcode = cpu_to_le16(event);
1218 if (hdev)
1219 hdr->index = cpu_to_le16(hdev->id);
1220 else
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001221 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001222 hdr->len = cpu_to_le16(data_len);
1223
1224 if (data)
1225 memcpy(skb_put(skb, data_len), data, data_len);
1226
Marcel Holtmann97e0bde2012-02-22 13:49:28 +01001227 /* Time stamp */
1228 __net_timestamp(skb);
1229
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001230 hci_send_to_control(skb, skip_sk);
1231 kfree_skb(skb);
1232
1233 return 0;
1234}
1235
1236static int new_settings(struct hci_dev *hdev, struct sock *skip)
1237{
1238 __le32 ev;
1239
1240 ev = cpu_to_le32(get_current_settings(hdev));
1241
1242 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1243}
1244
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001245struct cmd_lookup {
1246 struct sock *sk;
1247 struct hci_dev *hdev;
1248 u8 mgmt_status;
1249};
1250
1251static void settings_rsp(struct pending_cmd *cmd, void *data)
1252{
1253 struct cmd_lookup *match = data;
1254
1255 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1256
1257 list_del(&cmd->list);
1258
1259 if (match->sk == NULL) {
1260 match->sk = cmd->sk;
1261 sock_hold(match->sk);
1262 }
1263
1264 mgmt_pending_free(cmd);
1265}
1266
1267static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1268{
1269 u8 *status = data;
1270
1271 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1272 mgmt_pending_remove(cmd);
1273}
1274
Johan Hedberge6fe7982013-10-02 15:45:22 +03001275static u8 mgmt_bredr_support(struct hci_dev *hdev)
1276{
1277 if (!lmp_bredr_capable(hdev))
1278 return MGMT_STATUS_NOT_SUPPORTED;
1279 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1280 return MGMT_STATUS_REJECTED;
1281 else
1282 return MGMT_STATUS_SUCCESS;
1283}
1284
1285static u8 mgmt_le_support(struct hci_dev *hdev)
1286{
1287 if (!lmp_le_capable(hdev))
1288 return MGMT_STATUS_NOT_SUPPORTED;
1289 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1290 return MGMT_STATUS_REJECTED;
1291 else
1292 return MGMT_STATUS_SUCCESS;
1293}
1294
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001295static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1296{
1297 struct pending_cmd *cmd;
1298 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001299 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001300 bool changed;
1301
1302 BT_DBG("status 0x%02x", status);
1303
1304 hci_dev_lock(hdev);
1305
1306 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1307 if (!cmd)
1308 goto unlock;
1309
1310 if (status) {
1311 u8 mgmt_err = mgmt_status(status);
1312 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001313 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001314 goto remove_cmd;
1315 }
1316
1317 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001318 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001319 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1320 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001321
1322 if (hdev->discov_timeout > 0) {
1323 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1324 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1325 to);
1326 }
1327 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001328 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1329 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001330 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001331
1332 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1333
1334 if (changed)
1335 new_settings(hdev, cmd->sk);
1336
Marcel Holtmann970ba522013-10-15 06:33:57 -07001337 /* When the discoverable mode gets changed, make sure
1338 * that class of device has the limited discoverable
1339 * bit correctly set.
1340 */
1341 hci_req_init(&req, hdev);
1342 update_class(&req);
1343 hci_req_run(&req, NULL);
1344
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001345remove_cmd:
1346 mgmt_pending_remove(cmd);
1347
1348unlock:
1349 hci_dev_unlock(hdev);
1350}
1351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001352static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001353 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001355 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001356 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001357 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001358 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001359 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001360 int err;
1361
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001362 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001363
Johan Hedberg9a43e252013-10-20 19:00:07 +03001364 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1365 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001366 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001367 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001368
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001369 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001370 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1371 MGMT_STATUS_INVALID_PARAMS);
1372
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001373 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001374
1375 /* Disabling discoverable requires that no timeout is set,
1376 * and enabling limited discoverable requires a timeout.
1377 */
1378 if ((cp->val == 0x00 && timeout > 0) ||
1379 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001380 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001381 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001383 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001384
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001385 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001386 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001387 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001388 goto failed;
1389 }
1390
1391 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001392 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001393 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001394 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001395 goto failed;
1396 }
1397
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001398 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001399 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001400 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001401 goto failed;
1402 }
1403
1404 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001405 bool changed = false;
1406
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001407 /* Setting limited discoverable when powered off is
1408 * not a valid operation since it requires a timeout
1409 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1410 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001411 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1412 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1413 changed = true;
1414 }
1415
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001416 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001417 if (err < 0)
1418 goto failed;
1419
1420 if (changed)
1421 err = new_settings(hdev, sk);
1422
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001423 goto failed;
1424 }
1425
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001426 /* If the current mode is the same, then just update the timeout
1427 * value with the new value. And if only the timeout gets updated,
1428 * then no need for any HCI transactions.
1429 */
1430 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1431 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1432 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001433 cancel_delayed_work(&hdev->discov_off);
1434 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001435
Marcel Holtmann36261542013-10-15 08:28:51 -07001436 if (cp->val && hdev->discov_timeout > 0) {
1437 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001438 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001439 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001440 }
1441
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001442 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001443 goto failed;
1444 }
1445
1446 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1447 if (!cmd) {
1448 err = -ENOMEM;
1449 goto failed;
1450 }
1451
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001452 /* Cancel any potential discoverable timeout that might be
1453 * still active and store new timeout value. The arming of
1454 * the timeout happens in the complete handler.
1455 */
1456 cancel_delayed_work(&hdev->discov_off);
1457 hdev->discov_timeout = timeout;
1458
Johan Hedbergb456f872013-10-19 23:38:22 +03001459 /* Limited discoverable mode */
1460 if (cp->val == 0x02)
1461 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1462 else
1463 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1464
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001465 hci_req_init(&req, hdev);
1466
Johan Hedberg9a43e252013-10-20 19:00:07 +03001467 /* The procedure for LE-only controllers is much simpler - just
1468 * update the advertising data.
1469 */
1470 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1471 goto update_ad;
1472
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001473 scan = SCAN_PAGE;
1474
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001475 if (cp->val) {
1476 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001477
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001478 if (cp->val == 0x02) {
1479 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001480 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001481 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1482 hci_cp.iac_lap[1] = 0x8b;
1483 hci_cp.iac_lap[2] = 0x9e;
1484 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1485 hci_cp.iac_lap[4] = 0x8b;
1486 hci_cp.iac_lap[5] = 0x9e;
1487 } else {
1488 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001489 hci_cp.num_iac = 1;
1490 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1491 hci_cp.iac_lap[1] = 0x8b;
1492 hci_cp.iac_lap[2] = 0x9e;
1493 }
1494
1495 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1496 (hci_cp.num_iac * 3) + 1, &hci_cp);
1497
1498 scan |= SCAN_INQUIRY;
1499 } else {
1500 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1501 }
1502
1503 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001504
Johan Hedberg9a43e252013-10-20 19:00:07 +03001505update_ad:
1506 update_adv_data(&req);
1507
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001508 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001509 if (err < 0)
1510 mgmt_pending_remove(cmd);
1511
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001512failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001513 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001514 return err;
1515}
1516
Johan Hedberg406d7802013-03-15 17:07:09 -05001517static void write_fast_connectable(struct hci_request *req, bool enable)
1518{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001519 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001520 struct hci_cp_write_page_scan_activity acp;
1521 u8 type;
1522
Johan Hedberg547003b2013-10-21 16:51:53 +03001523 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1524 return;
1525
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001526 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1527 return;
1528
Johan Hedberg406d7802013-03-15 17:07:09 -05001529 if (enable) {
1530 type = PAGE_SCAN_TYPE_INTERLACED;
1531
1532 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001533 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001534 } else {
1535 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1536
1537 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001538 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001539 }
1540
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001541 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001542
Johan Hedbergbd98b992013-03-15 17:07:13 -05001543 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1544 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1545 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1546 sizeof(acp), &acp);
1547
1548 if (hdev->page_scan_type != type)
1549 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001550}
1551
Johan Hedberg2b76f452013-03-15 17:07:04 -05001552static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1553{
1554 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001555 struct mgmt_mode *cp;
1556 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001557
1558 BT_DBG("status 0x%02x", status);
1559
1560 hci_dev_lock(hdev);
1561
1562 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1563 if (!cmd)
1564 goto unlock;
1565
Johan Hedberg37438c12013-10-14 16:20:05 +03001566 if (status) {
1567 u8 mgmt_err = mgmt_status(status);
1568 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1569 goto remove_cmd;
1570 }
1571
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001572 cp = cmd->param;
1573 if (cp->val)
1574 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1575 else
1576 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1577
Johan Hedberg2b76f452013-03-15 17:07:04 -05001578 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1579
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001580 if (changed)
1581 new_settings(hdev, cmd->sk);
1582
Johan Hedberg37438c12013-10-14 16:20:05 +03001583remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001584 mgmt_pending_remove(cmd);
1585
1586unlock:
1587 hci_dev_unlock(hdev);
1588}
1589
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001590static int set_connectable_update_settings(struct hci_dev *hdev,
1591 struct sock *sk, u8 val)
1592{
1593 bool changed = false;
1594 int err;
1595
1596 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1597 changed = true;
1598
1599 if (val) {
1600 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1601 } else {
1602 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1603 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1604 }
1605
1606 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1607 if (err < 0)
1608 return err;
1609
1610 if (changed)
1611 return new_settings(hdev, sk);
1612
1613 return 0;
1614}
1615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001616static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001617 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001618{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001619 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001620 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001621 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001622 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001624
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001625 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001626
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001627 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1628 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001629 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001630 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001631
Johan Hedberga7e80f22013-01-09 16:05:19 +02001632 if (cp->val != 0x00 && cp->val != 0x01)
1633 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1634 MGMT_STATUS_INVALID_PARAMS);
1635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001636 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001637
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001638 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001639 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001640 goto failed;
1641 }
1642
1643 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001644 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001645 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001646 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001647 goto failed;
1648 }
1649
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001650 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1651 if (!cmd) {
1652 err = -ENOMEM;
1653 goto failed;
1654 }
1655
Johan Hedberg2b76f452013-03-15 17:07:04 -05001656 hci_req_init(&req, hdev);
1657
Johan Hedberg9a43e252013-10-20 19:00:07 +03001658 /* If BR/EDR is not enabled and we disable advertising as a
1659 * by-product of disabling connectable, we need to update the
1660 * advertising flags.
1661 */
1662 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1663 if (!cp->val) {
1664 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1665 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1666 }
1667 update_adv_data(&req);
1668 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001669 if (cp->val) {
1670 scan = SCAN_PAGE;
1671 } else {
1672 scan = 0;
1673
1674 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001675 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001676 cancel_delayed_work(&hdev->discov_off);
1677 }
1678
1679 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1680 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001681
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001682 /* If we're going from non-connectable to connectable or
1683 * vice-versa when fast connectable is enabled ensure that fast
1684 * connectable gets disabled. write_fast_connectable won't do
1685 * anything if the page scan parameters are already what they
1686 * should be.
1687 */
1688 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001689 write_fast_connectable(&req, false);
1690
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001691 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1692 hci_conn_num(hdev, LE_LINK) == 0) {
1693 disable_advertising(&req);
1694 enable_advertising(&req);
1695 }
1696
Johan Hedberg2b76f452013-03-15 17:07:04 -05001697 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001698 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001699 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001700 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001701 err = set_connectable_update_settings(hdev, sk,
1702 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001703 goto failed;
1704 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001705
1706failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001707 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001708 return err;
1709}
1710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001711static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001712 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001713{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001714 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001715 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001716 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001718 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001719
Johan Hedberga7e80f22013-01-09 16:05:19 +02001720 if (cp->val != 0x00 && cp->val != 0x01)
1721 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1722 MGMT_STATUS_INVALID_PARAMS);
1723
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001724 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001725
1726 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001727 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001728 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001729 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001730
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001731 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001732 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001733 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001734
Marcel Holtmann55594352013-10-06 16:11:57 -07001735 if (changed)
1736 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001737
Marcel Holtmann55594352013-10-06 16:11:57 -07001738unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001739 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001740 return err;
1741}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001742
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001743static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1744 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001745{
1746 struct mgmt_mode *cp = data;
1747 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001748 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001749 int err;
1750
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001751 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001752
Johan Hedberge6fe7982013-10-02 15:45:22 +03001753 status = mgmt_bredr_support(hdev);
1754 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001755 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001756 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001757
Johan Hedberga7e80f22013-01-09 16:05:19 +02001758 if (cp->val != 0x00 && cp->val != 0x01)
1759 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1760 MGMT_STATUS_INVALID_PARAMS);
1761
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001762 hci_dev_lock(hdev);
1763
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001764 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001765 bool changed = false;
1766
1767 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001768 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001769 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1770 changed = true;
1771 }
1772
1773 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1774 if (err < 0)
1775 goto failed;
1776
1777 if (changed)
1778 err = new_settings(hdev, sk);
1779
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001780 goto failed;
1781 }
1782
1783 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001784 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001785 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001786 goto failed;
1787 }
1788
1789 val = !!cp->val;
1790
1791 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1792 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1793 goto failed;
1794 }
1795
1796 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1797 if (!cmd) {
1798 err = -ENOMEM;
1799 goto failed;
1800 }
1801
1802 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1803 if (err < 0) {
1804 mgmt_pending_remove(cmd);
1805 goto failed;
1806 }
1807
1808failed:
1809 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001810 return err;
1811}
1812
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001813static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001814{
1815 struct mgmt_mode *cp = data;
1816 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001817 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001818 int err;
1819
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001820 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001821
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001822 status = mgmt_bredr_support(hdev);
1823 if (status)
1824 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1825
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001826 if (!lmp_ssp_capable(hdev))
1827 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1828 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001829
Johan Hedberga7e80f22013-01-09 16:05:19 +02001830 if (cp->val != 0x00 && cp->val != 0x01)
1831 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1832 MGMT_STATUS_INVALID_PARAMS);
1833
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001834 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02001835
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001836 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001837 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001838
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001839 if (cp->val) {
1840 changed = !test_and_set_bit(HCI_SSP_ENABLED,
1841 &hdev->dev_flags);
1842 } else {
1843 changed = test_and_clear_bit(HCI_SSP_ENABLED,
1844 &hdev->dev_flags);
1845 if (!changed)
1846 changed = test_and_clear_bit(HCI_HS_ENABLED,
1847 &hdev->dev_flags);
1848 else
1849 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02001850 }
1851
1852 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1853 if (err < 0)
1854 goto failed;
1855
1856 if (changed)
1857 err = new_settings(hdev, sk);
1858
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001859 goto failed;
1860 }
1861
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001862 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
1863 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01001864 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1865 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001866 goto failed;
1867 }
1868
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001869 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001870 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
1871 goto failed;
1872 }
1873
1874 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
1875 if (!cmd) {
1876 err = -ENOMEM;
1877 goto failed;
1878 }
1879
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001880 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001881 if (err < 0) {
1882 mgmt_pending_remove(cmd);
1883 goto failed;
1884 }
1885
1886failed:
1887 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001888 return err;
1889}
1890
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001891static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001892{
1893 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07001894 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001895 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07001896 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001898 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001899
Johan Hedberge6fe7982013-10-02 15:45:22 +03001900 status = mgmt_bredr_support(hdev);
1901 if (status)
1902 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001903
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07001904 if (!lmp_ssp_capable(hdev))
1905 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1906 MGMT_STATUS_NOT_SUPPORTED);
1907
1908 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
1909 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1910 MGMT_STATUS_REJECTED);
1911
Johan Hedberga7e80f22013-01-09 16:05:19 +02001912 if (cp->val != 0x00 && cp->val != 0x01)
1913 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1914 MGMT_STATUS_INVALID_PARAMS);
1915
Marcel Holtmannee392692013-10-01 22:59:23 -07001916 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001917
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001918 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07001919 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001920 } else {
1921 if (hdev_is_powered(hdev)) {
1922 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
1923 MGMT_STATUS_REJECTED);
1924 goto unlock;
1925 }
1926
Marcel Holtmannee392692013-10-01 22:59:23 -07001927 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07001928 }
Marcel Holtmannee392692013-10-01 22:59:23 -07001929
1930 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
1931 if (err < 0)
1932 goto unlock;
1933
1934 if (changed)
1935 err = new_settings(hdev, sk);
1936
1937unlock:
1938 hci_dev_unlock(hdev);
1939 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02001940}
1941
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001942static void le_enable_complete(struct hci_dev *hdev, u8 status)
1943{
1944 struct cmd_lookup match = { NULL, hdev };
1945
1946 if (status) {
1947 u8 mgmt_err = mgmt_status(status);
1948
1949 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
1950 &mgmt_err);
1951 return;
1952 }
1953
1954 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
1955
1956 new_settings(hdev, match.sk);
1957
1958 if (match.sk)
1959 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001960
1961 /* Make sure the controller has a good default for
1962 * advertising data. Restrict the update to when LE
1963 * has actually been enabled. During power on, the
1964 * update in powered_update_hci will take care of it.
1965 */
1966 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
1967 struct hci_request req;
1968
1969 hci_dev_lock(hdev);
1970
1971 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001972 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07001973 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001974 hci_req_run(&req, NULL);
1975
1976 hci_dev_unlock(hdev);
1977 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001978}
1979
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001980static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02001981{
1982 struct mgmt_mode *cp = data;
1983 struct hci_cp_write_le_host_supported hci_cp;
1984 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03001985 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001986 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02001987 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02001988
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001989 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02001990
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001991 if (!lmp_le_capable(hdev))
1992 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1993 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08001994
Johan Hedberga7e80f22013-01-09 16:05:19 +02001995 if (cp->val != 0x00 && cp->val != 0x01)
1996 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
1997 MGMT_STATUS_INVALID_PARAMS);
1998
Johan Hedbergc73eee92013-04-19 18:35:21 +03001999 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002000 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002001 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2002 MGMT_STATUS_REJECTED);
2003
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002004 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002005
2006 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002007 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002008
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002009 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002010 bool changed = false;
2011
2012 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2013 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2014 changed = true;
2015 }
2016
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002017 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2018 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002019 changed = true;
2020 }
2021
Johan Hedberg06199cf2012-02-22 16:37:11 +02002022 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2023 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002024 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002025
2026 if (changed)
2027 err = new_settings(hdev, sk);
2028
Johan Hedberg1de028c2012-02-29 19:55:35 -08002029 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002030 }
2031
Johan Hedberg4375f102013-09-25 13:26:10 +03002032 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2033 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002034 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002035 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002036 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002037 }
2038
2039 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2040 if (!cmd) {
2041 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002042 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002043 }
2044
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002045 hci_req_init(&req, hdev);
2046
Johan Hedberg06199cf2012-02-22 16:37:11 +02002047 memset(&hci_cp, 0, sizeof(hci_cp));
2048
2049 if (val) {
2050 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002051 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002052 } else {
2053 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2054 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002055 }
2056
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002057 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2058 &hci_cp);
2059
2060 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302061 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002062 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002063
Johan Hedberg1de028c2012-02-29 19:55:35 -08002064unlock:
2065 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002066 return err;
2067}
2068
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002069/* This is a helper function to test for pending mgmt commands that can
2070 * cause CoD or EIR HCI commands. We can only allow one such pending
2071 * mgmt command at a time since otherwise we cannot easily track what
2072 * the current values are, will be, and based on that calculate if a new
2073 * HCI command needs to be sent and if yes with what value.
2074 */
2075static bool pending_eir_or_class(struct hci_dev *hdev)
2076{
2077 struct pending_cmd *cmd;
2078
2079 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2080 switch (cmd->opcode) {
2081 case MGMT_OP_ADD_UUID:
2082 case MGMT_OP_REMOVE_UUID:
2083 case MGMT_OP_SET_DEV_CLASS:
2084 case MGMT_OP_SET_POWERED:
2085 return true;
2086 }
2087 }
2088
2089 return false;
2090}
2091
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002092static const u8 bluetooth_base_uuid[] = {
2093 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2094 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2095};
2096
2097static u8 get_uuid_size(const u8 *uuid)
2098{
2099 u32 val;
2100
2101 if (memcmp(uuid, bluetooth_base_uuid, 12))
2102 return 128;
2103
2104 val = get_unaligned_le32(&uuid[12]);
2105 if (val > 0xffff)
2106 return 32;
2107
2108 return 16;
2109}
2110
Johan Hedberg92da6092013-03-15 17:06:55 -05002111static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2112{
2113 struct pending_cmd *cmd;
2114
2115 hci_dev_lock(hdev);
2116
2117 cmd = mgmt_pending_find(mgmt_op, hdev);
2118 if (!cmd)
2119 goto unlock;
2120
2121 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2122 hdev->dev_class, 3);
2123
2124 mgmt_pending_remove(cmd);
2125
2126unlock:
2127 hci_dev_unlock(hdev);
2128}
2129
2130static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2131{
2132 BT_DBG("status 0x%02x", status);
2133
2134 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2135}
2136
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002137static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002138{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002139 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002140 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002141 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002142 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002143 int err;
2144
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002145 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002146
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002147 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002148
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002149 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002150 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002151 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002152 goto failed;
2153 }
2154
Andre Guedes92c4c202012-06-07 19:05:44 -03002155 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002156 if (!uuid) {
2157 err = -ENOMEM;
2158 goto failed;
2159 }
2160
2161 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002162 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002163 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002164
Johan Hedbergde66aa62013-01-27 00:31:27 +02002165 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002166
Johan Hedberg890ea892013-03-15 17:06:52 -05002167 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002168
Johan Hedberg890ea892013-03-15 17:06:52 -05002169 update_class(&req);
2170 update_eir(&req);
2171
Johan Hedberg92da6092013-03-15 17:06:55 -05002172 err = hci_req_run(&req, add_uuid_complete);
2173 if (err < 0) {
2174 if (err != -ENODATA)
2175 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002176
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002177 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002178 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002179 goto failed;
2180 }
2181
2182 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002183 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002184 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002185 goto failed;
2186 }
2187
2188 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002189
2190failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002191 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002192 return err;
2193}
2194
Johan Hedberg24b78d02012-02-23 23:24:30 +02002195static bool enable_service_cache(struct hci_dev *hdev)
2196{
2197 if (!hdev_is_powered(hdev))
2198 return false;
2199
2200 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002201 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2202 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002203 return true;
2204 }
2205
2206 return false;
2207}
2208
Johan Hedberg92da6092013-03-15 17:06:55 -05002209static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2210{
2211 BT_DBG("status 0x%02x", status);
2212
2213 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2214}
2215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002216static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002217 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002218{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002219 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002220 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002221 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002222 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 -05002223 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002224 int err, found;
2225
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002226 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002227
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002228 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002229
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002230 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002231 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002232 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002233 goto unlock;
2234 }
2235
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002236 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002237 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002238
Johan Hedberg24b78d02012-02-23 23:24:30 +02002239 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002241 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002242 goto unlock;
2243 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002244
Johan Hedberg9246a862012-02-23 21:33:16 +02002245 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002246 }
2247
2248 found = 0;
2249
Johan Hedberg056341c2013-01-27 00:31:30 +02002250 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002251 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2252 continue;
2253
2254 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002255 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002256 found++;
2257 }
2258
2259 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002260 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002261 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002262 goto unlock;
2263 }
2264
Johan Hedberg9246a862012-02-23 21:33:16 +02002265update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002266 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002267
Johan Hedberg890ea892013-03-15 17:06:52 -05002268 update_class(&req);
2269 update_eir(&req);
2270
Johan Hedberg92da6092013-03-15 17:06:55 -05002271 err = hci_req_run(&req, remove_uuid_complete);
2272 if (err < 0) {
2273 if (err != -ENODATA)
2274 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002275
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002276 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002277 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002278 goto unlock;
2279 }
2280
2281 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002282 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002283 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002284 goto unlock;
2285 }
2286
2287 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002288
2289unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002290 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002291 return err;
2292}
2293
Johan Hedberg92da6092013-03-15 17:06:55 -05002294static void set_class_complete(struct hci_dev *hdev, u8 status)
2295{
2296 BT_DBG("status 0x%02x", status);
2297
2298 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2299}
2300
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002301static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002302 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002303{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002304 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002305 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002306 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002307 int err;
2308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002309 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002310
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002311 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002312 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2313 MGMT_STATUS_NOT_SUPPORTED);
2314
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002315 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002316
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002317 if (pending_eir_or_class(hdev)) {
2318 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2319 MGMT_STATUS_BUSY);
2320 goto unlock;
2321 }
2322
2323 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2324 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2325 MGMT_STATUS_INVALID_PARAMS);
2326 goto unlock;
2327 }
2328
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002329 hdev->major_class = cp->major;
2330 hdev->minor_class = cp->minor;
2331
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002332 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002333 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002334 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002335 goto unlock;
2336 }
2337
Johan Hedberg890ea892013-03-15 17:06:52 -05002338 hci_req_init(&req, hdev);
2339
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002340 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002341 hci_dev_unlock(hdev);
2342 cancel_delayed_work_sync(&hdev->service_cache);
2343 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002344 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002345 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002346
Johan Hedberg890ea892013-03-15 17:06:52 -05002347 update_class(&req);
2348
Johan Hedberg92da6092013-03-15 17:06:55 -05002349 err = hci_req_run(&req, set_class_complete);
2350 if (err < 0) {
2351 if (err != -ENODATA)
2352 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002353
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002354 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002355 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002356 goto unlock;
2357 }
2358
2359 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002360 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002361 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002362 goto unlock;
2363 }
2364
2365 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002366
Johan Hedbergb5235a62012-02-21 14:32:24 +02002367unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002368 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002369 return err;
2370}
2371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002372static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002373 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002374{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002375 struct mgmt_cp_load_link_keys *cp = data;
Szymon Janc4e51eae2011-02-25 19:05:48 +01002376 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002377 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002378 int i;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002379
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002380 BT_DBG("request for %s", hdev->name);
2381
2382 if (!lmp_bredr_capable(hdev))
2383 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2384 MGMT_STATUS_NOT_SUPPORTED);
2385
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002386 key_count = __le16_to_cpu(cp->key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002387
Johan Hedberg86742e12011-11-07 23:13:38 +02002388 expected_len = sizeof(*cp) + key_count *
2389 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002390 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002391 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002392 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002393 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002394 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002395 }
2396
Johan Hedberg4ae14302013-01-20 14:27:13 +02002397 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2398 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2399 MGMT_STATUS_INVALID_PARAMS);
2400
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002401 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002402 key_count);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002403
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002404 for (i = 0; i < key_count; i++) {
2405 struct mgmt_link_key_info *key = &cp->keys[i];
2406
Marcel Holtmann8e991132014-01-10 02:07:25 -08002407 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002408 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2409 MGMT_STATUS_INVALID_PARAMS);
2410 }
2411
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002412 hci_dev_lock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002413
2414 hci_link_keys_clear(hdev);
2415
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002416 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002417 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2418 &hdev->dev_flags);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002419 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002420 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2421 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002422
2423 if (changed)
2424 new_settings(hdev, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002425
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002426 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002427 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002428
Johan Hedberg58e92932014-06-24 14:00:26 +03002429 /* Always ignore debug keys and require a new pairing if
2430 * the user wants to use them.
2431 */
2432 if (key->type == HCI_LK_DEBUG_COMBINATION)
2433 continue;
2434
Johan Hedberg7652ff62014-06-24 13:15:49 +03002435 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2436 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002437 }
2438
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002439 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002440
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002441 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002442
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002443 return 0;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002444}
2445
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002446static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002447 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002448{
2449 struct mgmt_ev_device_unpaired ev;
2450
2451 bacpy(&ev.addr.bdaddr, bdaddr);
2452 ev.addr.type = addr_type;
2453
2454 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002455 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002456}
2457
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002458static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002459 u16 len)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002460{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002461 struct mgmt_cp_unpair_device *cp = data;
2462 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002463 struct hci_cp_disconnect dc;
2464 struct pending_cmd *cmd;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002465 struct hci_conn *conn;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002466 int err;
2467
Johan Hedberga8a1d192011-11-10 15:54:38 +02002468 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002469 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2470 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002471
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002472 if (!bdaddr_type_is_valid(cp->addr.type))
2473 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2474 MGMT_STATUS_INVALID_PARAMS,
2475 &rp, sizeof(rp));
2476
Johan Hedberg118da702013-01-20 14:27:20 +02002477 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2478 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2479 MGMT_STATUS_INVALID_PARAMS,
2480 &rp, sizeof(rp));
2481
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002482 hci_dev_lock(hdev);
2483
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002484 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002485 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002486 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002487 goto unlock;
2488 }
2489
Johan Hedberge0b2b272014-02-18 17:14:31 +02002490 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002491 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002492 } else {
2493 u8 addr_type;
2494
2495 if (cp->addr.type == BDADDR_LE_PUBLIC)
2496 addr_type = ADDR_LE_DEV_PUBLIC;
2497 else
2498 addr_type = ADDR_LE_DEV_RANDOM;
2499
Johan Hedberga7ec7332014-02-18 17:14:35 +02002500 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2501
Andre Guedesa9b0a042014-02-26 20:21:52 -03002502 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2503
Johan Hedberge0b2b272014-02-18 17:14:31 +02002504 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2505 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002506
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002507 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002508 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002509 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002510 goto unlock;
2511 }
2512
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002513 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002514 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002515 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002516 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002517 else
2518 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002519 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002520 } else {
2521 conn = NULL;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002522 }
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002523
Johan Hedberga8a1d192011-11-10 15:54:38 +02002524 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002525 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002526 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002527 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002528 goto unlock;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002529 }
2530
Johan Hedberg124f6e32012-02-09 13:50:12 +02002531 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002532 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002533 if (!cmd) {
2534 err = -ENOMEM;
2535 goto unlock;
2536 }
2537
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002538 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002539 dc.reason = 0x13; /* Remote User Terminated Connection */
2540 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2541 if (err < 0)
2542 mgmt_pending_remove(cmd);
2543
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002544unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002545 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02002546 return err;
2547}
2548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002549static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002550 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002551{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002552 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002553 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002554 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002555 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002556 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002557 int err;
2558
2559 BT_DBG("");
2560
Johan Hedberg06a63b12013-01-20 14:27:21 +02002561 memset(&rp, 0, sizeof(rp));
2562 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2563 rp.addr.type = cp->addr.type;
2564
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002565 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002566 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2567 MGMT_STATUS_INVALID_PARAMS,
2568 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002569
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002570 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002571
2572 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002573 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2574 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002575 goto failed;
2576 }
2577
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002578 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002579 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2580 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002581 goto failed;
2582 }
2583
Andre Guedes591f47f2012-04-24 21:02:49 -03002584 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002585 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2586 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002587 else
2588 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002589
Vishal Agarwalf9607272012-06-13 05:32:43 +05302590 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2592 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002593 goto failed;
2594 }
2595
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002596 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002597 if (!cmd) {
2598 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002599 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002600 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002601
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002602 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002603 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002604
2605 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2606 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002607 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002608
2609failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002610 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002611 return err;
2612}
2613
Andre Guedes57c14772012-04-24 21:02:50 -03002614static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002615{
2616 switch (link_type) {
2617 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002618 switch (addr_type) {
2619 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002620 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002621
Johan Hedberg48264f02011-11-09 13:58:58 +02002622 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002623 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002624 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002625 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002626
Johan Hedberg4c659c32011-11-07 23:13:39 +02002627 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002628 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002629 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002630 }
2631}
2632
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002633static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2634 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002635{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002636 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002637 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002638 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002639 int err;
2640 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002641
2642 BT_DBG("");
2643
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002644 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002645
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002646 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002647 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002648 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002649 goto unlock;
2650 }
2651
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002652 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002653 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2654 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002655 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002656 }
2657
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002658 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002659 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002660 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002661 err = -ENOMEM;
2662 goto unlock;
2663 }
2664
Johan Hedberg2784eb42011-01-21 13:56:35 +02002665 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002666 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002667 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2668 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002669 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002670 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002671 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002672 continue;
2673 i++;
2674 }
2675
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002676 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002677
Johan Hedberg4c659c32011-11-07 23:13:39 +02002678 /* Recalculate length in case of filtered SCO connections, etc */
2679 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002680
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002681 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002682 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002683
Johan Hedberga38528f2011-01-22 06:46:43 +02002684 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002685
2686unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002687 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002688 return err;
2689}
2690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002691static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002692 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002693{
2694 struct pending_cmd *cmd;
2695 int err;
2696
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002697 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002698 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002699 if (!cmd)
2700 return -ENOMEM;
2701
Johan Hedbergd8457692012-02-17 14:24:57 +02002702 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002703 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002704 if (err < 0)
2705 mgmt_pending_remove(cmd);
2706
2707 return err;
2708}
2709
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002710static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002711 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002712{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002713 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002714 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002715 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002716 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002717 int err;
2718
2719 BT_DBG("");
2720
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002721 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002722
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002723 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002726 goto failed;
2727 }
2728
Johan Hedbergd8457692012-02-17 14:24:57 +02002729 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002730 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002731 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002733 goto failed;
2734 }
2735
2736 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002737 struct mgmt_cp_pin_code_neg_reply ncp;
2738
2739 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002740
2741 BT_ERR("PIN code is not 16 bytes long");
2742
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002743 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002744 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002745 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002746 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002747
2748 goto failed;
2749 }
2750
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002751 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002752 if (!cmd) {
2753 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002754 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002755 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002756
Johan Hedbergd8457692012-02-17 14:24:57 +02002757 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002758 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002759 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002760
2761 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2762 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002763 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002764
2765failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002766 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002767 return err;
2768}
2769
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002770static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2771 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002772{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002773 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002774
2775 BT_DBG("");
2776
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002777 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2778 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2779 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2780
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002781 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002782
2783 hdev->io_capability = cp->io_capability;
2784
2785 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002786 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002787
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002788 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002789
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002790 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2791 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002792}
2793
Gustavo Padovan6039aa732012-05-23 04:04:18 -03002794static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002795{
2796 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002797 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002798
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002799 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002800 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2801 continue;
2802
Johan Hedberge9a416b2011-02-19 12:05:56 -03002803 if (cmd->user_data != conn)
2804 continue;
2805
2806 return cmd;
2807 }
2808
2809 return NULL;
2810}
2811
2812static void pairing_complete(struct pending_cmd *cmd, u8 status)
2813{
2814 struct mgmt_rp_pair_device rp;
2815 struct hci_conn *conn = cmd->user_data;
2816
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002817 bacpy(&rp.addr.bdaddr, &conn->dst);
2818 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002819
Johan Hedbergaee9b2182012-02-18 15:07:59 +02002820 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002821 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002822
2823 /* So we don't get further callbacks for this connection */
2824 conn->connect_cfm_cb = NULL;
2825 conn->security_cfm_cb = NULL;
2826 conn->disconn_cfm_cb = NULL;
2827
David Herrmann76a68ba2013-04-06 20:28:37 +02002828 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002829
Johan Hedberga664b5b2011-02-19 12:06:02 -03002830 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002831}
2832
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002833void mgmt_smp_complete(struct hci_conn *conn, bool complete)
2834{
2835 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
2836 struct pending_cmd *cmd;
2837
2838 cmd = find_pairing(conn);
2839 if (cmd)
2840 pairing_complete(cmd, status);
2841}
2842
Johan Hedberge9a416b2011-02-19 12:05:56 -03002843static void pairing_complete_cb(struct hci_conn *conn, u8 status)
2844{
2845 struct pending_cmd *cmd;
2846
2847 BT_DBG("status %u", status);
2848
Johan Hedberg56e5cb82011-11-08 20:40:16 +02002849 cmd = find_pairing(conn);
2850 if (!cmd)
2851 BT_DBG("Unable to find a pending command");
2852 else
Johan Hedberge2113262012-02-18 15:20:03 +02002853 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002854}
2855
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002856static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05302857{
2858 struct pending_cmd *cmd;
2859
2860 BT_DBG("status %u", status);
2861
2862 if (!status)
2863 return;
2864
2865 cmd = find_pairing(conn);
2866 if (!cmd)
2867 BT_DBG("Unable to find a pending command");
2868 else
2869 pairing_complete(cmd, mgmt_status(status));
2870}
2871
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002872static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002873 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002874{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002875 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02002876 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002877 struct pending_cmd *cmd;
2878 u8 sec_level, auth_type;
2879 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002880 int err;
2881
2882 BT_DBG("");
2883
Szymon Jancf950a30e2013-01-18 12:48:07 +01002884 memset(&rp, 0, sizeof(rp));
2885 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2886 rp.addr.type = cp->addr.type;
2887
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002888 if (!bdaddr_type_is_valid(cp->addr.type))
2889 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2890 MGMT_STATUS_INVALID_PARAMS,
2891 &rp, sizeof(rp));
2892
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002893 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
2894 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2895 MGMT_STATUS_INVALID_PARAMS,
2896 &rp, sizeof(rp));
2897
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002898 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002899
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002900 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01002901 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
2902 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002903 goto unlock;
2904 }
2905
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03002906 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02002907 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002908
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002909 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03002910 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
2911 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002912 } else {
2913 u8 addr_type;
2914
2915 /* Convert from L2CAP channel address type to HCI address type
2916 */
2917 if (cp->addr.type == BDADDR_LE_PUBLIC)
2918 addr_type = ADDR_LE_DEV_PUBLIC;
2919 else
2920 addr_type = ADDR_LE_DEV_RANDOM;
2921
2922 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03002923 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03002924 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002925
Ville Tervo30e76272011-02-22 16:10:53 -03002926 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002927 int status;
2928
2929 if (PTR_ERR(conn) == -EBUSY)
2930 status = MGMT_STATUS_BUSY;
2931 else
2932 status = MGMT_STATUS_CONNECT_FAILED;
2933
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02002935 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002936 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002937 goto unlock;
2938 }
2939
2940 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02002941 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002942 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002943 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03002944 goto unlock;
2945 }
2946
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002947 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002948 if (!cmd) {
2949 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02002950 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002951 goto unlock;
2952 }
2953
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002954 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002955 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002956 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02002957 conn->security_cfm_cb = pairing_complete_cb;
2958 conn->disconn_cfm_cb = pairing_complete_cb;
2959 } else {
2960 conn->connect_cfm_cb = le_pairing_complete_cb;
2961 conn->security_cfm_cb = le_pairing_complete_cb;
2962 conn->disconn_cfm_cb = le_pairing_complete_cb;
2963 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03002964
Johan Hedberge9a416b2011-02-19 12:05:56 -03002965 conn->io_capability = cp->io_cap;
2966 cmd->user_data = conn;
2967
2968 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002969 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03002970 pairing_complete(cmd, 0);
2971
2972 err = 0;
2973
2974unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002975 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03002976 return err;
2977}
2978
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
2980 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02002981{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02002982 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02002983 struct pending_cmd *cmd;
2984 struct hci_conn *conn;
2985 int err;
2986
2987 BT_DBG("");
2988
Johan Hedberg28424702012-02-02 04:02:29 +02002989 hci_dev_lock(hdev);
2990
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002991 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002992 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002993 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002994 goto unlock;
2995 }
2996
Johan Hedberg28424702012-02-02 04:02:29 +02002997 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
2998 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002999 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003000 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003001 goto unlock;
3002 }
3003
3004 conn = cmd->user_data;
3005
3006 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003007 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003008 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003009 goto unlock;
3010 }
3011
3012 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003014 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003015 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003016unlock:
3017 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003018 return err;
3019}
3020
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003021static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003022 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003023 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003024{
Johan Hedberga5c29682011-02-19 12:05:57 -03003025 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003026 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003027 int err;
3028
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003029 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003030
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003031 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003032 err = cmd_complete(sk, hdev->id, mgmt_op,
3033 MGMT_STATUS_NOT_POWERED, addr,
3034 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003035 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003036 }
3037
Johan Hedberg1707c602013-03-15 17:07:15 -05003038 if (addr->type == BDADDR_BREDR)
3039 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003040 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003041 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003042
Johan Hedberg272d90d2012-02-09 15:26:12 +02003043 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003044 err = cmd_complete(sk, hdev->id, mgmt_op,
3045 MGMT_STATUS_NOT_CONNECTED, addr,
3046 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003047 goto done;
3048 }
3049
Johan Hedberg1707c602013-03-15 17:07:15 -05003050 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003051 /* Continue with pairing via SMP. The hdev lock must be
3052 * released as SMP may try to recquire it for crypto
3053 * purposes.
3054 */
3055 hci_dev_unlock(hdev);
Brian Gix5fe57d92011-12-21 16:12:13 -08003056 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Johan Hedbergc73f94b2014-06-13 10:22:28 +03003057 hci_dev_lock(hdev);
Brian Gix47c15e22011-11-16 13:53:14 -08003058
Brian Gix5fe57d92011-12-21 16:12:13 -08003059 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003060 err = cmd_complete(sk, hdev->id, mgmt_op,
3061 MGMT_STATUS_SUCCESS, addr,
3062 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003063 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003064 err = cmd_complete(sk, hdev->id, mgmt_op,
3065 MGMT_STATUS_FAILED, addr,
3066 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003067
Brian Gix47c15e22011-11-16 13:53:14 -08003068 goto done;
3069 }
3070
Johan Hedberg1707c602013-03-15 17:07:15 -05003071 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003072 if (!cmd) {
3073 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003074 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003075 }
3076
Brian Gix0df4c182011-11-16 13:53:13 -08003077 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003078 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3079 struct hci_cp_user_passkey_reply cp;
3080
Johan Hedberg1707c602013-03-15 17:07:15 -05003081 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003082 cp.passkey = passkey;
3083 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3084 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003085 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3086 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003087
Johan Hedberga664b5b2011-02-19 12:06:02 -03003088 if (err < 0)
3089 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003090
Brian Gix0df4c182011-11-16 13:53:13 -08003091done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003092 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003093 return err;
3094}
3095
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303096static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3097 void *data, u16 len)
3098{
3099 struct mgmt_cp_pin_code_neg_reply *cp = data;
3100
3101 BT_DBG("");
3102
Johan Hedberg1707c602013-03-15 17:07:15 -05003103 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303104 MGMT_OP_PIN_CODE_NEG_REPLY,
3105 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3106}
3107
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003108static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3109 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003110{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003111 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003112
3113 BT_DBG("");
3114
3115 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003116 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003117 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003118
Johan Hedberg1707c602013-03-15 17:07:15 -05003119 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003120 MGMT_OP_USER_CONFIRM_REPLY,
3121 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003122}
3123
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003124static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003125 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003126{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003127 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003128
3129 BT_DBG("");
3130
Johan Hedberg1707c602013-03-15 17:07:15 -05003131 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003132 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3133 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003134}
3135
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3137 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003138{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003139 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003140
3141 BT_DBG("");
3142
Johan Hedberg1707c602013-03-15 17:07:15 -05003143 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003144 MGMT_OP_USER_PASSKEY_REPLY,
3145 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003146}
3147
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003148static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003150{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003151 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003152
3153 BT_DBG("");
3154
Johan Hedberg1707c602013-03-15 17:07:15 -05003155 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003156 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3157 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003158}
3159
Johan Hedberg13928972013-03-15 17:07:00 -05003160static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003161{
Johan Hedberg13928972013-03-15 17:07:00 -05003162 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003163 struct hci_cp_write_local_name cp;
3164
Johan Hedberg13928972013-03-15 17:07:00 -05003165 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003166
Johan Hedberg890ea892013-03-15 17:06:52 -05003167 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003168}
3169
Johan Hedberg13928972013-03-15 17:07:00 -05003170static void set_name_complete(struct hci_dev *hdev, u8 status)
3171{
3172 struct mgmt_cp_set_local_name *cp;
3173 struct pending_cmd *cmd;
3174
3175 BT_DBG("status 0x%02x", status);
3176
3177 hci_dev_lock(hdev);
3178
3179 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3180 if (!cmd)
3181 goto unlock;
3182
3183 cp = cmd->param;
3184
3185 if (status)
3186 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3187 mgmt_status(status));
3188 else
3189 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3190 cp, sizeof(*cp));
3191
3192 mgmt_pending_remove(cmd);
3193
3194unlock:
3195 hci_dev_unlock(hdev);
3196}
3197
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003198static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003199 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003200{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003201 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003202 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003203 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003204 int err;
3205
3206 BT_DBG("");
3207
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003208 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003209
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003210 /* If the old values are the same as the new ones just return a
3211 * direct command complete event.
3212 */
3213 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3214 !memcmp(hdev->short_name, cp->short_name,
3215 sizeof(hdev->short_name))) {
3216 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3217 data, len);
3218 goto failed;
3219 }
3220
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003221 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003222
Johan Hedbergb5235a62012-02-21 14:32:24 +02003223 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003224 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003225
3226 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003227 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003228 if (err < 0)
3229 goto failed;
3230
3231 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003232 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003233
Johan Hedbergb5235a62012-02-21 14:32:24 +02003234 goto failed;
3235 }
3236
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003237 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003238 if (!cmd) {
3239 err = -ENOMEM;
3240 goto failed;
3241 }
3242
Johan Hedberg13928972013-03-15 17:07:00 -05003243 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3244
Johan Hedberg890ea892013-03-15 17:06:52 -05003245 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003246
3247 if (lmp_bredr_capable(hdev)) {
3248 update_name(&req);
3249 update_eir(&req);
3250 }
3251
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003252 /* The name is stored in the scan response data and so
3253 * no need to udpate the advertising data here.
3254 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003255 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003256 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003257
Johan Hedberg13928972013-03-15 17:07:00 -05003258 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003259 if (err < 0)
3260 mgmt_pending_remove(cmd);
3261
3262failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003263 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003264 return err;
3265}
3266
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003267static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003268 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003269{
Szymon Jancc35938b2011-03-22 13:12:21 +01003270 struct pending_cmd *cmd;
3271 int err;
3272
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003273 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003274
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003275 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003276
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003277 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003278 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003279 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003280 goto unlock;
3281 }
3282
Andre Guedes9a1a1992012-07-24 15:03:48 -03003283 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003284 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003286 goto unlock;
3287 }
3288
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003289 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003290 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003291 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003292 goto unlock;
3293 }
3294
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003295 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003296 if (!cmd) {
3297 err = -ENOMEM;
3298 goto unlock;
3299 }
3300
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003301 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3302 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3303 0, NULL);
3304 else
3305 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3306
Szymon Jancc35938b2011-03-22 13:12:21 +01003307 if (err < 0)
3308 mgmt_pending_remove(cmd);
3309
3310unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003311 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003312 return err;
3313}
3314
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003315static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003316 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003317{
Szymon Janc2763eda2011-03-22 13:12:22 +01003318 int err;
3319
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003321
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003322 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003323
Marcel Holtmannec109112014-01-10 02:07:30 -08003324 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3325 struct mgmt_cp_add_remote_oob_data *cp = data;
3326 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003327
Marcel Holtmannec109112014-01-10 02:07:30 -08003328 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3329 cp->hash, cp->randomizer);
3330 if (err < 0)
3331 status = MGMT_STATUS_FAILED;
3332 else
3333 status = MGMT_STATUS_SUCCESS;
3334
3335 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3336 status, &cp->addr, sizeof(cp->addr));
3337 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3338 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3339 u8 status;
3340
3341 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3342 cp->hash192,
3343 cp->randomizer192,
3344 cp->hash256,
3345 cp->randomizer256);
3346 if (err < 0)
3347 status = MGMT_STATUS_FAILED;
3348 else
3349 status = MGMT_STATUS_SUCCESS;
3350
3351 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3352 status, &cp->addr, sizeof(cp->addr));
3353 } else {
3354 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3355 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3356 MGMT_STATUS_INVALID_PARAMS);
3357 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003358
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003359 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003360 return err;
3361}
3362
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003363static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003364 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003365{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003366 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003367 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003368 int err;
3369
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003370 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003371
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003372 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003373
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003374 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003375 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003376 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003377 else
Szymon Janca6785be2012-12-13 15:11:21 +01003378 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003380 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003381 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003383 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003384 return err;
3385}
3386
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003387static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3388{
3389 struct pending_cmd *cmd;
3390 u8 type;
3391 int err;
3392
3393 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3394
3395 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3396 if (!cmd)
3397 return -ENOENT;
3398
3399 type = hdev->discovery.type;
3400
3401 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3402 &type, sizeof(type));
3403 mgmt_pending_remove(cmd);
3404
3405 return err;
3406}
3407
Andre Guedes7c307722013-04-30 15:29:28 -03003408static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3409{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003410 unsigned long timeout = 0;
3411
Andre Guedes7c307722013-04-30 15:29:28 -03003412 BT_DBG("status %d", status);
3413
3414 if (status) {
3415 hci_dev_lock(hdev);
3416 mgmt_start_discovery_failed(hdev, status);
3417 hci_dev_unlock(hdev);
3418 return;
3419 }
3420
3421 hci_dev_lock(hdev);
3422 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3423 hci_dev_unlock(hdev);
3424
3425 switch (hdev->discovery.type) {
3426 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003427 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003428 break;
3429
3430 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003431 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003432 break;
3433
3434 case DISCOV_TYPE_BREDR:
3435 break;
3436
3437 default:
3438 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3439 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003440
3441 if (!timeout)
3442 return;
3443
3444 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003445}
3446
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003447static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003449{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003450 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003451 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003452 struct hci_cp_le_set_scan_param param_cp;
3453 struct hci_cp_le_set_scan_enable enable_cp;
3454 struct hci_cp_inquiry inq_cp;
3455 struct hci_request req;
3456 /* General inquiry access code (GIAC) */
3457 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003458 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003459 int err;
3460
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003461 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003462
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003463 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003464
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003465 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003466 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003467 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003468 goto failed;
3469 }
3470
Andre Guedes642be6c2012-03-21 00:03:37 -03003471 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3472 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3473 MGMT_STATUS_BUSY);
3474 goto failed;
3475 }
3476
Johan Hedbergff9ef572012-01-04 14:23:45 +02003477 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003478 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003479 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003480 goto failed;
3481 }
3482
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003483 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003484 if (!cmd) {
3485 err = -ENOMEM;
3486 goto failed;
3487 }
3488
Andre Guedes4aab14e2012-02-17 20:39:36 -03003489 hdev->discovery.type = cp->type;
3490
Andre Guedes7c307722013-04-30 15:29:28 -03003491 hci_req_init(&req, hdev);
3492
Andre Guedes4aab14e2012-02-17 20:39:36 -03003493 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003494 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003495 status = mgmt_bredr_support(hdev);
3496 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003497 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003498 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003499 mgmt_pending_remove(cmd);
3500 goto failed;
3501 }
3502
Andre Guedes7c307722013-04-30 15:29:28 -03003503 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3504 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3505 MGMT_STATUS_BUSY);
3506 mgmt_pending_remove(cmd);
3507 goto failed;
3508 }
3509
3510 hci_inquiry_cache_flush(hdev);
3511
3512 memset(&inq_cp, 0, sizeof(inq_cp));
3513 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003514 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003515 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003516 break;
3517
3518 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003519 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003520 status = mgmt_le_support(hdev);
3521 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003522 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003523 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003524 mgmt_pending_remove(cmd);
3525 goto failed;
3526 }
3527
Andre Guedes7c307722013-04-30 15:29:28 -03003528 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003529 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003530 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3531 MGMT_STATUS_NOT_SUPPORTED);
3532 mgmt_pending_remove(cmd);
3533 goto failed;
3534 }
3535
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003536 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003537 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3538 MGMT_STATUS_REJECTED);
3539 mgmt_pending_remove(cmd);
3540 goto failed;
3541 }
3542
Andre Guedesc54c3862014-02-26 20:21:50 -03003543 /* If controller is scanning, it means the background scanning
3544 * is running. Thus, we should temporarily stop it in order to
3545 * set the discovery scanning parameters.
3546 */
3547 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3548 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003549
3550 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003551
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003552 /* All active scans will be done with either a resolvable
3553 * private address (when privacy feature has been enabled)
3554 * or unresolvable private address.
3555 */
3556 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003557 if (err < 0) {
3558 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3559 MGMT_STATUS_FAILED);
3560 mgmt_pending_remove(cmd);
3561 goto failed;
3562 }
3563
Andre Guedes7c307722013-04-30 15:29:28 -03003564 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003565 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3566 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003567 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003568 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3569 &param_cp);
3570
3571 memset(&enable_cp, 0, sizeof(enable_cp));
3572 enable_cp.enable = LE_SCAN_ENABLE;
3573 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3574 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3575 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003576 break;
3577
Andre Guedesf39799f2012-02-17 20:39:35 -03003578 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003579 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3580 MGMT_STATUS_INVALID_PARAMS);
3581 mgmt_pending_remove(cmd);
3582 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003583 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003584
Andre Guedes7c307722013-04-30 15:29:28 -03003585 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003586 if (err < 0)
3587 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003588 else
3589 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003590
3591failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003592 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003593 return err;
3594}
3595
Andre Guedes1183fdc2013-04-30 15:29:35 -03003596static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3597{
3598 struct pending_cmd *cmd;
3599 int err;
3600
3601 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3602 if (!cmd)
3603 return -ENOENT;
3604
3605 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3606 &hdev->discovery.type, sizeof(hdev->discovery.type));
3607 mgmt_pending_remove(cmd);
3608
3609 return err;
3610}
3611
Andre Guedes0e05bba2013-04-30 15:29:33 -03003612static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3613{
3614 BT_DBG("status %d", status);
3615
3616 hci_dev_lock(hdev);
3617
3618 if (status) {
3619 mgmt_stop_discovery_failed(hdev, status);
3620 goto unlock;
3621 }
3622
3623 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3624
3625unlock:
3626 hci_dev_unlock(hdev);
3627}
3628
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003629static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003631{
Johan Hedbergd9306502012-02-20 23:25:18 +02003632 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003633 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003634 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003635 int err;
3636
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003637 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003638
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003639 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003640
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003641 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003642 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003643 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3644 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003645 goto unlock;
3646 }
3647
3648 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003649 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003650 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3651 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003652 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003653 }
3654
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003655 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003656 if (!cmd) {
3657 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003658 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003659 }
3660
Andre Guedes0e05bba2013-04-30 15:29:33 -03003661 hci_req_init(&req, hdev);
3662
Johan Hedberg21a60d32014-06-10 14:05:58 +03003663 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003664
Johan Hedberg21a60d32014-06-10 14:05:58 +03003665 err = hci_req_run(&req, stop_discovery_complete);
3666 if (!err) {
3667 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003668 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003669 }
3670
Johan Hedberg21a60d32014-06-10 14:05:58 +03003671 mgmt_pending_remove(cmd);
3672
3673 /* If no HCI commands were sent we're done */
3674 if (err == -ENODATA) {
3675 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3676 &mgmt_cp->type, sizeof(mgmt_cp->type));
3677 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3678 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003679
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003680unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003681 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003682 return err;
3683}
3684
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003685static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003686 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003687{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003688 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003689 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003690 int err;
3691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003692 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003693
Johan Hedberg561aafb2012-01-04 13:31:59 +02003694 hci_dev_lock(hdev);
3695
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003696 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003697 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3698 MGMT_STATUS_FAILED, &cp->addr,
3699 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003700 goto failed;
3701 }
3702
Johan Hedberga198e7b2012-02-17 14:27:06 +02003703 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003704 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003705 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3706 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3707 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003708 goto failed;
3709 }
3710
3711 if (cp->name_known) {
3712 e->name_state = NAME_KNOWN;
3713 list_del(&e->list);
3714 } else {
3715 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02003716 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003717 }
3718
Johan Hedberge3846622013-01-09 15:29:33 +02003719 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3720 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003721
3722failed:
3723 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003724 return err;
3725}
3726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003727static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003728 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003729{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003730 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003731 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003732 int err;
3733
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003734 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003735
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003736 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003737 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3738 MGMT_STATUS_INVALID_PARAMS,
3739 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003740
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003741 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003742
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003743 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003744 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003745 status = MGMT_STATUS_FAILED;
Antti Julku7fbec222011-06-15 12:01:15 +03003746 else
Szymon Janca6785be2012-12-13 15:11:21 +01003747 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003748
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003749 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003750 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003752 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003753
3754 return err;
3755}
3756
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003757static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003758 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003759{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003760 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003761 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003762 int err;
3763
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003764 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003765
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003766 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003767 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3768 MGMT_STATUS_INVALID_PARAMS,
3769 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003770
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003771 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003772
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003773 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Antti Julku7fbec222011-06-15 12:01:15 +03003774 if (err < 0)
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003775 status = MGMT_STATUS_INVALID_PARAMS;
Antti Julku7fbec222011-06-15 12:01:15 +03003776 else
Szymon Janca6785be2012-12-13 15:11:21 +01003777 status = MGMT_STATUS_SUCCESS;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003778
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003779 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003780 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003781
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003782 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003783
3784 return err;
3785}
3786
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003787static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3788 u16 len)
3789{
3790 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003791 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003792 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003793 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003794
3795 BT_DBG("%s", hdev->name);
3796
Szymon Jancc72d4b82012-03-16 16:02:57 +01003797 source = __le16_to_cpu(cp->source);
3798
3799 if (source > 0x0002)
3800 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3801 MGMT_STATUS_INVALID_PARAMS);
3802
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003803 hci_dev_lock(hdev);
3804
Szymon Jancc72d4b82012-03-16 16:02:57 +01003805 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003806 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
3807 hdev->devid_product = __le16_to_cpu(cp->product);
3808 hdev->devid_version = __le16_to_cpu(cp->version);
3809
3810 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
3811
Johan Hedberg890ea892013-03-15 17:06:52 -05003812 hci_req_init(&req, hdev);
3813 update_eir(&req);
3814 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003815
3816 hci_dev_unlock(hdev);
3817
3818 return err;
3819}
3820
Johan Hedberg4375f102013-09-25 13:26:10 +03003821static void set_advertising_complete(struct hci_dev *hdev, u8 status)
3822{
3823 struct cmd_lookup match = { NULL, hdev };
3824
3825 if (status) {
3826 u8 mgmt_err = mgmt_status(status);
3827
3828 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
3829 cmd_status_rsp, &mgmt_err);
3830 return;
3831 }
3832
3833 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
3834 &match);
3835
3836 new_settings(hdev, match.sk);
3837
3838 if (match.sk)
3839 sock_put(match.sk);
3840}
3841
Marcel Holtmann21b51872013-10-10 09:47:53 -07003842static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
3843 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03003844{
3845 struct mgmt_mode *cp = data;
3846 struct pending_cmd *cmd;
3847 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03003848 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03003849 int err;
3850
3851 BT_DBG("request for %s", hdev->name);
3852
Johan Hedberge6fe7982013-10-02 15:45:22 +03003853 status = mgmt_le_support(hdev);
3854 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03003855 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003856 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03003857
3858 if (cp->val != 0x00 && cp->val != 0x01)
3859 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3860 MGMT_STATUS_INVALID_PARAMS);
3861
3862 hci_dev_lock(hdev);
3863
3864 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003865 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003866
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02003867 /* The following conditions are ones which mean that we should
3868 * not do any HCI communication but directly send a mgmt
3869 * response to user space (after toggling the flag if
3870 * necessary).
3871 */
3872 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07003873 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03003874 bool changed = false;
3875
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003876 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
3877 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03003878 changed = true;
3879 }
3880
3881 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
3882 if (err < 0)
3883 goto unlock;
3884
3885 if (changed)
3886 err = new_settings(hdev, sk);
3887
3888 goto unlock;
3889 }
3890
3891 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
3892 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
3893 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
3894 MGMT_STATUS_BUSY);
3895 goto unlock;
3896 }
3897
3898 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
3899 if (!cmd) {
3900 err = -ENOMEM;
3901 goto unlock;
3902 }
3903
3904 hci_req_init(&req, hdev);
3905
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07003906 if (val)
3907 enable_advertising(&req);
3908 else
3909 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03003910
3911 err = hci_req_run(&req, set_advertising_complete);
3912 if (err < 0)
3913 mgmt_pending_remove(cmd);
3914
3915unlock:
3916 hci_dev_unlock(hdev);
3917 return err;
3918}
3919
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003920static int set_static_address(struct sock *sk, struct hci_dev *hdev,
3921 void *data, u16 len)
3922{
3923 struct mgmt_cp_set_static_address *cp = data;
3924 int err;
3925
3926 BT_DBG("%s", hdev->name);
3927
Marcel Holtmann62af4442013-10-02 22:10:32 -07003928 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003929 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07003930 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07003931
3932 if (hdev_is_powered(hdev))
3933 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
3934 MGMT_STATUS_REJECTED);
3935
3936 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
3937 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
3938 return cmd_status(sk, hdev->id,
3939 MGMT_OP_SET_STATIC_ADDRESS,
3940 MGMT_STATUS_INVALID_PARAMS);
3941
3942 /* Two most significant bits shall be set */
3943 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
3944 return cmd_status(sk, hdev->id,
3945 MGMT_OP_SET_STATIC_ADDRESS,
3946 MGMT_STATUS_INVALID_PARAMS);
3947 }
3948
3949 hci_dev_lock(hdev);
3950
3951 bacpy(&hdev->static_addr, &cp->bdaddr);
3952
3953 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
3954
3955 hci_dev_unlock(hdev);
3956
3957 return err;
3958}
3959
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003960static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
3961 void *data, u16 len)
3962{
3963 struct mgmt_cp_set_scan_params *cp = data;
3964 __u16 interval, window;
3965 int err;
3966
3967 BT_DBG("%s", hdev->name);
3968
3969 if (!lmp_le_capable(hdev))
3970 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3971 MGMT_STATUS_NOT_SUPPORTED);
3972
3973 interval = __le16_to_cpu(cp->interval);
3974
3975 if (interval < 0x0004 || interval > 0x4000)
3976 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3977 MGMT_STATUS_INVALID_PARAMS);
3978
3979 window = __le16_to_cpu(cp->window);
3980
3981 if (window < 0x0004 || window > 0x4000)
3982 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3983 MGMT_STATUS_INVALID_PARAMS);
3984
Marcel Holtmann899e1072013-10-14 09:55:32 -07003985 if (window > interval)
3986 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
3987 MGMT_STATUS_INVALID_PARAMS);
3988
Marcel Holtmann14b49b92013-10-11 08:23:20 -07003989 hci_dev_lock(hdev);
3990
3991 hdev->le_scan_interval = interval;
3992 hdev->le_scan_window = window;
3993
3994 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
3995
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03003996 /* If background scan is running, restart it so new parameters are
3997 * loaded.
3998 */
3999 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4000 hdev->discovery.state == DISCOVERY_STOPPED) {
4001 struct hci_request req;
4002
4003 hci_req_init(&req, hdev);
4004
4005 hci_req_add_le_scan_disable(&req);
4006 hci_req_add_le_passive_scan(&req);
4007
4008 hci_req_run(&req, NULL);
4009 }
4010
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004011 hci_dev_unlock(hdev);
4012
4013 return err;
4014}
4015
Johan Hedberg33e38b32013-03-15 17:07:05 -05004016static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4017{
4018 struct pending_cmd *cmd;
4019
4020 BT_DBG("status 0x%02x", status);
4021
4022 hci_dev_lock(hdev);
4023
4024 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4025 if (!cmd)
4026 goto unlock;
4027
4028 if (status) {
4029 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4030 mgmt_status(status));
4031 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004032 struct mgmt_mode *cp = cmd->param;
4033
4034 if (cp->val)
4035 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4036 else
4037 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4038
Johan Hedberg33e38b32013-03-15 17:07:05 -05004039 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4040 new_settings(hdev, cmd->sk);
4041 }
4042
4043 mgmt_pending_remove(cmd);
4044
4045unlock:
4046 hci_dev_unlock(hdev);
4047}
4048
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004049static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004050 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004051{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004052 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004053 struct pending_cmd *cmd;
4054 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004055 int err;
4056
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004057 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004058
Johan Hedberg56f87902013-10-02 13:43:13 +03004059 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4060 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004061 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4062 MGMT_STATUS_NOT_SUPPORTED);
4063
Johan Hedberga7e80f22013-01-09 16:05:19 +02004064 if (cp->val != 0x00 && cp->val != 0x01)
4065 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4066 MGMT_STATUS_INVALID_PARAMS);
4067
Johan Hedberg5400c042012-02-21 16:40:33 +02004068 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004069 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004070 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004071
4072 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004073 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004074 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004075
4076 hci_dev_lock(hdev);
4077
Johan Hedberg05cbf292013-03-15 17:07:07 -05004078 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4079 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4080 MGMT_STATUS_BUSY);
4081 goto unlock;
4082 }
4083
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004084 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4085 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4086 hdev);
4087 goto unlock;
4088 }
4089
Johan Hedberg33e38b32013-03-15 17:07:05 -05004090 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4091 data, len);
4092 if (!cmd) {
4093 err = -ENOMEM;
4094 goto unlock;
4095 }
4096
4097 hci_req_init(&req, hdev);
4098
Johan Hedberg406d7802013-03-15 17:07:09 -05004099 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004100
4101 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004102 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004103 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004104 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004105 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004106 }
4107
Johan Hedberg33e38b32013-03-15 17:07:05 -05004108unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004109 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004110
Antti Julkuf6422ec2011-06-22 13:11:56 +03004111 return err;
4112}
4113
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004114static void set_bredr_scan(struct hci_request *req)
4115{
4116 struct hci_dev *hdev = req->hdev;
4117 u8 scan = 0;
4118
4119 /* Ensure that fast connectable is disabled. This function will
4120 * not do anything if the page scan parameters are already what
4121 * they should be.
4122 */
4123 write_fast_connectable(req, false);
4124
4125 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4126 scan |= SCAN_PAGE;
4127 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4128 scan |= SCAN_INQUIRY;
4129
4130 if (scan)
4131 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4132}
4133
Johan Hedberg0663ca22013-10-02 13:43:14 +03004134static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4135{
4136 struct pending_cmd *cmd;
4137
4138 BT_DBG("status 0x%02x", status);
4139
4140 hci_dev_lock(hdev);
4141
4142 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4143 if (!cmd)
4144 goto unlock;
4145
4146 if (status) {
4147 u8 mgmt_err = mgmt_status(status);
4148
4149 /* We need to restore the flag if related HCI commands
4150 * failed.
4151 */
4152 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4153
4154 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4155 } else {
4156 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4157 new_settings(hdev, cmd->sk);
4158 }
4159
4160 mgmt_pending_remove(cmd);
4161
4162unlock:
4163 hci_dev_unlock(hdev);
4164}
4165
4166static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4167{
4168 struct mgmt_mode *cp = data;
4169 struct pending_cmd *cmd;
4170 struct hci_request req;
4171 int err;
4172
4173 BT_DBG("request for %s", hdev->name);
4174
4175 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4176 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4177 MGMT_STATUS_NOT_SUPPORTED);
4178
4179 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4180 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4181 MGMT_STATUS_REJECTED);
4182
4183 if (cp->val != 0x00 && cp->val != 0x01)
4184 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4185 MGMT_STATUS_INVALID_PARAMS);
4186
4187 hci_dev_lock(hdev);
4188
4189 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4190 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4191 goto unlock;
4192 }
4193
4194 if (!hdev_is_powered(hdev)) {
4195 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004196 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4197 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4198 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4199 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4200 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4201 }
4202
4203 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4204
4205 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4206 if (err < 0)
4207 goto unlock;
4208
4209 err = new_settings(hdev, sk);
4210 goto unlock;
4211 }
4212
4213 /* Reject disabling when powered on */
4214 if (!cp->val) {
4215 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4216 MGMT_STATUS_REJECTED);
4217 goto unlock;
4218 }
4219
4220 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4221 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4222 MGMT_STATUS_BUSY);
4223 goto unlock;
4224 }
4225
4226 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4227 if (!cmd) {
4228 err = -ENOMEM;
4229 goto unlock;
4230 }
4231
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004232 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004233 * generates the correct flags.
4234 */
4235 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4236
4237 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004238
4239 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4240 set_bredr_scan(&req);
4241
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004242 /* Since only the advertising data flags will change, there
4243 * is no need to update the scan response data.
4244 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004245 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004246
Johan Hedberg0663ca22013-10-02 13:43:14 +03004247 err = hci_req_run(&req, set_bredr_complete);
4248 if (err < 0)
4249 mgmt_pending_remove(cmd);
4250
4251unlock:
4252 hci_dev_unlock(hdev);
4253 return err;
4254}
4255
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004256static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4257 void *data, u16 len)
4258{
4259 struct mgmt_mode *cp = data;
4260 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004261 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004262 int err;
4263
4264 BT_DBG("request for %s", hdev->name);
4265
4266 status = mgmt_bredr_support(hdev);
4267 if (status)
4268 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4269 status);
4270
Marcel Holtmann5afeac142014-01-10 02:07:27 -08004271 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004272 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004273 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4274 MGMT_STATUS_NOT_SUPPORTED);
4275
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004276 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004277 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4278 MGMT_STATUS_INVALID_PARAMS);
4279
4280 hci_dev_lock(hdev);
4281
4282 if (!hdev_is_powered(hdev)) {
4283 bool changed;
4284
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004285 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004286 changed = !test_and_set_bit(HCI_SC_ENABLED,
4287 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004288 if (cp->val == 0x02)
4289 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4290 else
4291 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4292 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004293 changed = test_and_clear_bit(HCI_SC_ENABLED,
4294 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004295 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4296 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004297
4298 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4299 if (err < 0)
4300 goto failed;
4301
4302 if (changed)
4303 err = new_settings(hdev, sk);
4304
4305 goto failed;
4306 }
4307
4308 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4309 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4310 MGMT_STATUS_BUSY);
4311 goto failed;
4312 }
4313
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004314 val = !!cp->val;
4315
4316 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4317 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004318 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4319 goto failed;
4320 }
4321
4322 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4323 if (!cmd) {
4324 err = -ENOMEM;
4325 goto failed;
4326 }
4327
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004328 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004329 if (err < 0) {
4330 mgmt_pending_remove(cmd);
4331 goto failed;
4332 }
4333
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004334 if (cp->val == 0x02)
4335 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4336 else
4337 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4338
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004339failed:
4340 hci_dev_unlock(hdev);
4341 return err;
4342}
4343
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004344static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4345 void *data, u16 len)
4346{
4347 struct mgmt_mode *cp = data;
4348 bool changed;
4349 int err;
4350
4351 BT_DBG("request for %s", hdev->name);
4352
4353 if (cp->val != 0x00 && cp->val != 0x01)
4354 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4355 MGMT_STATUS_INVALID_PARAMS);
4356
4357 hci_dev_lock(hdev);
4358
4359 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004360 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4361 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004362 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004363 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4364 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004365
4366 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4367 if (err < 0)
4368 goto unlock;
4369
4370 if (changed)
4371 err = new_settings(hdev, sk);
4372
4373unlock:
4374 hci_dev_unlock(hdev);
4375 return err;
4376}
4377
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004378static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4379 u16 len)
4380{
4381 struct mgmt_cp_set_privacy *cp = cp_data;
4382 bool changed;
4383 int err;
4384
4385 BT_DBG("request for %s", hdev->name);
4386
4387 if (!lmp_le_capable(hdev))
4388 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4389 MGMT_STATUS_NOT_SUPPORTED);
4390
4391 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4392 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4393 MGMT_STATUS_INVALID_PARAMS);
4394
4395 if (hdev_is_powered(hdev))
4396 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4397 MGMT_STATUS_REJECTED);
4398
4399 hci_dev_lock(hdev);
4400
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004401 /* If user space supports this command it is also expected to
4402 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4403 */
4404 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4405
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004406 if (cp->privacy) {
4407 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4408 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4409 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4410 } else {
4411 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4412 memset(hdev->irk, 0, sizeof(hdev->irk));
4413 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4414 }
4415
4416 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4417 if (err < 0)
4418 goto unlock;
4419
4420 if (changed)
4421 err = new_settings(hdev, sk);
4422
4423unlock:
4424 hci_dev_unlock(hdev);
4425 return err;
4426}
4427
Johan Hedberg41edf162014-02-18 10:19:35 +02004428static bool irk_is_valid(struct mgmt_irk_info *irk)
4429{
4430 switch (irk->addr.type) {
4431 case BDADDR_LE_PUBLIC:
4432 return true;
4433
4434 case BDADDR_LE_RANDOM:
4435 /* Two most significant bits shall be set */
4436 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4437 return false;
4438 return true;
4439 }
4440
4441 return false;
4442}
4443
4444static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4445 u16 len)
4446{
4447 struct mgmt_cp_load_irks *cp = cp_data;
4448 u16 irk_count, expected_len;
4449 int i, err;
4450
4451 BT_DBG("request for %s", hdev->name);
4452
4453 if (!lmp_le_capable(hdev))
4454 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4455 MGMT_STATUS_NOT_SUPPORTED);
4456
4457 irk_count = __le16_to_cpu(cp->irk_count);
4458
4459 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4460 if (expected_len != len) {
4461 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004462 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004463 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4464 MGMT_STATUS_INVALID_PARAMS);
4465 }
4466
4467 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4468
4469 for (i = 0; i < irk_count; i++) {
4470 struct mgmt_irk_info *key = &cp->irks[i];
4471
4472 if (!irk_is_valid(key))
4473 return cmd_status(sk, hdev->id,
4474 MGMT_OP_LOAD_IRKS,
4475 MGMT_STATUS_INVALID_PARAMS);
4476 }
4477
4478 hci_dev_lock(hdev);
4479
4480 hci_smp_irks_clear(hdev);
4481
4482 for (i = 0; i < irk_count; i++) {
4483 struct mgmt_irk_info *irk = &cp->irks[i];
4484 u8 addr_type;
4485
4486 if (irk->addr.type == BDADDR_LE_PUBLIC)
4487 addr_type = ADDR_LE_DEV_PUBLIC;
4488 else
4489 addr_type = ADDR_LE_DEV_RANDOM;
4490
4491 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4492 BDADDR_ANY);
4493 }
4494
4495 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4496
4497 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4498
4499 hci_dev_unlock(hdev);
4500
4501 return err;
4502}
4503
Johan Hedberg3f706b72013-01-20 14:27:16 +02004504static bool ltk_is_valid(struct mgmt_ltk_info *key)
4505{
4506 if (key->master != 0x00 && key->master != 0x01)
4507 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004508
4509 switch (key->addr.type) {
4510 case BDADDR_LE_PUBLIC:
4511 return true;
4512
4513 case BDADDR_LE_RANDOM:
4514 /* Two most significant bits shall be set */
4515 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4516 return false;
4517 return true;
4518 }
4519
4520 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004521}
4522
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004523static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004524 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004525{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004526 struct mgmt_cp_load_long_term_keys *cp = cp_data;
4527 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004528 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004529
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004530 BT_DBG("request for %s", hdev->name);
4531
4532 if (!lmp_le_capable(hdev))
4533 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4534 MGMT_STATUS_NOT_SUPPORTED);
4535
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004536 key_count = __le16_to_cpu(cp->key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004537
4538 expected_len = sizeof(*cp) + key_count *
4539 sizeof(struct mgmt_ltk_info);
4540 if (expected_len != len) {
4541 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004542 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004543 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004544 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004545 }
4546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004547 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004548
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004549 for (i = 0; i < key_count; i++) {
4550 struct mgmt_ltk_info *key = &cp->keys[i];
4551
Johan Hedberg3f706b72013-01-20 14:27:16 +02004552 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004553 return cmd_status(sk, hdev->id,
4554 MGMT_OP_LOAD_LONG_TERM_KEYS,
4555 MGMT_STATUS_INVALID_PARAMS);
4556 }
4557
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004558 hci_dev_lock(hdev);
4559
4560 hci_smp_ltks_clear(hdev);
4561
4562 for (i = 0; i < key_count; i++) {
4563 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004564 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004565
4566 if (key->addr.type == BDADDR_LE_PUBLIC)
4567 addr_type = ADDR_LE_DEV_PUBLIC;
4568 else
4569 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004570
4571 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004572 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004573 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004574 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004575
Johan Hedberg61b43352014-05-29 19:36:53 +03004576 switch (key->type) {
4577 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004578 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004579 break;
4580 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004581 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004582 break;
4583 default:
4584 continue;
4585 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004586
Johan Hedberg35d70272014-02-19 14:57:47 +02004587 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004588 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004589 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004590 }
4591
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004592 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4593 NULL, 0);
4594
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004595 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004596
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004597 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004598}
4599
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004600struct cmd_conn_lookup {
4601 struct hci_conn *conn;
4602 bool valid_tx_power;
4603 u8 mgmt_status;
4604};
4605
4606static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4607{
4608 struct cmd_conn_lookup *match = data;
4609 struct mgmt_cp_get_conn_info *cp;
4610 struct mgmt_rp_get_conn_info rp;
4611 struct hci_conn *conn = cmd->user_data;
4612
4613 if (conn != match->conn)
4614 return;
4615
4616 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4617
4618 memset(&rp, 0, sizeof(rp));
4619 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4620 rp.addr.type = cp->addr.type;
4621
4622 if (!match->mgmt_status) {
4623 rp.rssi = conn->rssi;
4624
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004625 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004626 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004627 rp.max_tx_power = conn->max_tx_power;
4628 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004629 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004630 rp.max_tx_power = HCI_TX_POWER_INVALID;
4631 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004632 }
4633
4634 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4635 match->mgmt_status, &rp, sizeof(rp));
4636
4637 hci_conn_drop(conn);
4638
4639 mgmt_pending_remove(cmd);
4640}
4641
4642static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4643{
4644 struct hci_cp_read_rssi *cp;
4645 struct hci_conn *conn;
4646 struct cmd_conn_lookup match;
4647 u16 handle;
4648
4649 BT_DBG("status 0x%02x", status);
4650
4651 hci_dev_lock(hdev);
4652
4653 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004654 * otherwise we assume it's not valid. At the moment we assume that
4655 * either both or none of current and max values are valid to keep code
4656 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004657 */
4658 match.valid_tx_power = !status;
4659
4660 /* Commands sent in request are either Read RSSI or Read Transmit Power
4661 * Level so we check which one was last sent to retrieve connection
4662 * handle. Both commands have handle as first parameter so it's safe to
4663 * cast data on the same command struct.
4664 *
4665 * First command sent is always Read RSSI and we fail only if it fails.
4666 * In other case we simply override error to indicate success as we
4667 * already remembered if TX power value is actually valid.
4668 */
4669 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4670 if (!cp) {
4671 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4672 status = 0;
4673 }
4674
4675 if (!cp) {
4676 BT_ERR("invalid sent_cmd in response");
4677 goto unlock;
4678 }
4679
4680 handle = __le16_to_cpu(cp->handle);
4681 conn = hci_conn_hash_lookup_handle(hdev, handle);
4682 if (!conn) {
4683 BT_ERR("unknown handle (%d) in response", handle);
4684 goto unlock;
4685 }
4686
4687 match.conn = conn;
4688 match.mgmt_status = mgmt_status(status);
4689
4690 /* Cache refresh is complete, now reply for mgmt request for given
4691 * connection only.
4692 */
4693 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4694 get_conn_info_complete, &match);
4695
4696unlock:
4697 hci_dev_unlock(hdev);
4698}
4699
4700static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4701 u16 len)
4702{
4703 struct mgmt_cp_get_conn_info *cp = data;
4704 struct mgmt_rp_get_conn_info rp;
4705 struct hci_conn *conn;
4706 unsigned long conn_info_age;
4707 int err = 0;
4708
4709 BT_DBG("%s", hdev->name);
4710
4711 memset(&rp, 0, sizeof(rp));
4712 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4713 rp.addr.type = cp->addr.type;
4714
4715 if (!bdaddr_type_is_valid(cp->addr.type))
4716 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4717 MGMT_STATUS_INVALID_PARAMS,
4718 &rp, sizeof(rp));
4719
4720 hci_dev_lock(hdev);
4721
4722 if (!hdev_is_powered(hdev)) {
4723 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4724 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4725 goto unlock;
4726 }
4727
4728 if (cp->addr.type == BDADDR_BREDR)
4729 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4730 &cp->addr.bdaddr);
4731 else
4732 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4733
4734 if (!conn || conn->state != BT_CONNECTED) {
4735 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4736 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4737 goto unlock;
4738 }
4739
4740 /* To avoid client trying to guess when to poll again for information we
4741 * calculate conn info age as random value between min/max set in hdev.
4742 */
4743 conn_info_age = hdev->conn_info_min_age +
4744 prandom_u32_max(hdev->conn_info_max_age -
4745 hdev->conn_info_min_age);
4746
4747 /* Query controller to refresh cached values if they are too old or were
4748 * never read.
4749 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004750 if (time_after(jiffies, conn->conn_info_timestamp +
4751 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004752 !conn->conn_info_timestamp) {
4753 struct hci_request req;
4754 struct hci_cp_read_tx_power req_txp_cp;
4755 struct hci_cp_read_rssi req_rssi_cp;
4756 struct pending_cmd *cmd;
4757
4758 hci_req_init(&req, hdev);
4759 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4760 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4761 &req_rssi_cp);
4762
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004763 /* For LE links TX power does not change thus we don't need to
4764 * query for it once value is known.
4765 */
4766 if (!bdaddr_type_is_le(cp->addr.type) ||
4767 conn->tx_power == HCI_TX_POWER_INVALID) {
4768 req_txp_cp.handle = cpu_to_le16(conn->handle);
4769 req_txp_cp.type = 0x00;
4770 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4771 sizeof(req_txp_cp), &req_txp_cp);
4772 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004773
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004774 /* Max TX power needs to be read only once per connection */
4775 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
4776 req_txp_cp.handle = cpu_to_le16(conn->handle);
4777 req_txp_cp.type = 0x01;
4778 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4779 sizeof(req_txp_cp), &req_txp_cp);
4780 }
4781
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004782 err = hci_req_run(&req, conn_info_refresh_complete);
4783 if (err < 0)
4784 goto unlock;
4785
4786 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
4787 data, len);
4788 if (!cmd) {
4789 err = -ENOMEM;
4790 goto unlock;
4791 }
4792
4793 hci_conn_hold(conn);
4794 cmd->user_data = conn;
4795
4796 conn->conn_info_timestamp = jiffies;
4797 } else {
4798 /* Cache is valid, just reply with values cached in hci_conn */
4799 rp.rssi = conn->rssi;
4800 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004801 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004802
4803 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4804 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
4805 }
4806
4807unlock:
4808 hci_dev_unlock(hdev);
4809 return err;
4810}
4811
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004812static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004813 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
4814 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004815 bool var_len;
4816 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004817} mgmt_handlers[] = {
4818 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02004819 { read_version, false, MGMT_READ_VERSION_SIZE },
4820 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
4821 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
4822 { read_controller_info, false, MGMT_READ_INFO_SIZE },
4823 { set_powered, false, MGMT_SETTING_SIZE },
4824 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
4825 { set_connectable, false, MGMT_SETTING_SIZE },
4826 { set_fast_connectable, false, MGMT_SETTING_SIZE },
4827 { set_pairable, false, MGMT_SETTING_SIZE },
4828 { set_link_security, false, MGMT_SETTING_SIZE },
4829 { set_ssp, false, MGMT_SETTING_SIZE },
4830 { set_hs, false, MGMT_SETTING_SIZE },
4831 { set_le, false, MGMT_SETTING_SIZE },
4832 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
4833 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
4834 { add_uuid, false, MGMT_ADD_UUID_SIZE },
4835 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
4836 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
4837 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
4838 { disconnect, false, MGMT_DISCONNECT_SIZE },
4839 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
4840 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
4841 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
4842 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
4843 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
4844 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
4845 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
4846 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
4847 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
4848 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
4849 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
4850 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08004851 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02004852 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
4853 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
4854 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
4855 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
4856 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
4857 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004858 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03004859 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03004860 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004861 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004862 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004863 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004864 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004865 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02004866 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004867 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004868};
4869
4870
Johan Hedberg03811012010-12-08 00:21:06 +02004871int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
4872{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004873 void *buf;
4874 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02004875 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01004876 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004877 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02004878 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02004879 int err;
4880
4881 BT_DBG("got %zu bytes", msglen);
4882
4883 if (msglen < sizeof(*hdr))
4884 return -EINVAL;
4885
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03004886 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02004887 if (!buf)
4888 return -ENOMEM;
4889
4890 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
4891 err = -EFAULT;
4892 goto done;
4893 }
4894
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004895 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004896 opcode = __le16_to_cpu(hdr->opcode);
4897 index = __le16_to_cpu(hdr->index);
4898 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02004899
4900 if (len != msglen - sizeof(*hdr)) {
4901 err = -EINVAL;
4902 goto done;
4903 }
4904
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004905 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004906 hdev = hci_dev_get(index);
4907 if (!hdev) {
4908 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004909 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004910 goto done;
4911 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004912
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02004913 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
4914 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07004915 err = cmd_status(sk, index, opcode,
4916 MGMT_STATUS_INVALID_INDEX);
4917 goto done;
4918 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004919 }
4920
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004921 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004922 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02004923 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02004924 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004925 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004926 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02004927 }
4928
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004929 if ((hdev && opcode < MGMT_OP_READ_INFO) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004930 (!hdev && opcode >= MGMT_OP_READ_INFO)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004931 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004932 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004933 goto done;
4934 }
4935
Johan Hedbergbe22b542012-03-01 22:24:41 +02004936 handler = &mgmt_handlers[opcode];
4937
4938 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03004939 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02004940 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004941 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02004942 goto done;
4943 }
4944
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02004945 if (hdev)
4946 mgmt_init_hdev(sk, hdev);
4947
4948 cp = buf + sizeof(*hdr);
4949
Johan Hedbergbe22b542012-03-01 22:24:41 +02004950 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02004951 if (err < 0)
4952 goto done;
4953
Johan Hedberg03811012010-12-08 00:21:06 +02004954 err = msglen;
4955
4956done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004957 if (hdev)
4958 hci_dev_put(hdev);
4959
Johan Hedberg03811012010-12-08 00:21:06 +02004960 kfree(buf);
4961 return err;
4962}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004963
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004964void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004965{
Marcel Holtmann1514b892013-10-06 08:25:01 -07004966 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004967 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004968
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004969 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004970}
4971
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004972void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02004973{
Johan Hedberg5f159032012-03-02 03:13:19 +02004974 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02004975
Marcel Holtmann1514b892013-10-06 08:25:01 -07004976 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004977 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03004978
Johan Hedberg744cf192011-11-08 20:40:14 +02004979 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02004980
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07004981 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02004982}
4983
Andre Guedes6046dc32014-02-26 20:21:51 -03004984/* This function requires the caller holds hdev->lock */
4985static void restart_le_auto_conns(struct hci_dev *hdev)
4986{
4987 struct hci_conn_params *p;
4988
4989 list_for_each_entry(p, &hdev->le_conn_params, list) {
4990 if (p->auto_connect == HCI_AUTO_CONN_ALWAYS)
4991 hci_pend_le_conn_add(hdev, &p->addr, p->addr_type);
4992 }
4993}
4994
Johan Hedberg229ab392013-03-15 17:06:53 -05004995static void powered_complete(struct hci_dev *hdev, u8 status)
4996{
4997 struct cmd_lookup match = { NULL, hdev };
4998
4999 BT_DBG("status 0x%02x", status);
5000
5001 hci_dev_lock(hdev);
5002
Andre Guedes6046dc32014-02-26 20:21:51 -03005003 restart_le_auto_conns(hdev);
5004
Johan Hedberg229ab392013-03-15 17:06:53 -05005005 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5006
5007 new_settings(hdev, match.sk);
5008
5009 hci_dev_unlock(hdev);
5010
5011 if (match.sk)
5012 sock_put(match.sk);
5013}
5014
Johan Hedberg70da6242013-03-15 17:06:51 -05005015static int powered_update_hci(struct hci_dev *hdev)
5016{
Johan Hedberg890ea892013-03-15 17:06:52 -05005017 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005018 u8 link_sec;
5019
Johan Hedberg890ea892013-03-15 17:06:52 -05005020 hci_req_init(&req, hdev);
5021
Johan Hedberg70da6242013-03-15 17:06:51 -05005022 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5023 !lmp_host_ssp_capable(hdev)) {
5024 u8 ssp = 1;
5025
Johan Hedberg890ea892013-03-15 17:06:52 -05005026 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005027 }
5028
Johan Hedbergc73eee92013-04-19 18:35:21 +03005029 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5030 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005031 struct hci_cp_write_le_host_supported cp;
5032
5033 cp.le = 1;
5034 cp.simul = lmp_le_br_capable(hdev);
5035
5036 /* Check first if we already have the right
5037 * host state (host features set)
5038 */
5039 if (cp.le != lmp_host_le_capable(hdev) ||
5040 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005041 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5042 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005043 }
5044
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005045 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005046 /* Make sure the controller has a good default for
5047 * advertising data. This also applies to the case
5048 * where BR/EDR was toggled during the AUTO_OFF phase.
5049 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005050 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005051 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005052 update_scan_rsp_data(&req);
5053 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005054
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005055 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5056 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005057 }
5058
Johan Hedberg70da6242013-03-15 17:06:51 -05005059 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5060 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005061 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5062 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005063
5064 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005065 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5066 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005067 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005068 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005069 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005070 }
5071
Johan Hedberg229ab392013-03-15 17:06:53 -05005072 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005073}
5074
Johan Hedberg744cf192011-11-08 20:40:14 +02005075int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005076{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005077 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005078 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5079 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005080 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005081
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005082 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5083 return 0;
5084
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005085 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005086 if (powered_update_hci(hdev) == 0)
5087 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005088
Johan Hedberg229ab392013-03-15 17:06:53 -05005089 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5090 &match);
5091 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005092 }
5093
Johan Hedberg229ab392013-03-15 17:06:53 -05005094 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5095 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5096
5097 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5098 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5099 zero_cod, sizeof(zero_cod), NULL);
5100
5101new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005102 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005103
5104 if (match.sk)
5105 sock_put(match.sk);
5106
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005107 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005108}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005109
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005110void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005111{
5112 struct pending_cmd *cmd;
5113 u8 status;
5114
5115 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5116 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005117 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005118
5119 if (err == -ERFKILL)
5120 status = MGMT_STATUS_RFKILLED;
5121 else
5122 status = MGMT_STATUS_FAILED;
5123
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005124 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005125
5126 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005127}
5128
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005129void mgmt_discoverable_timeout(struct hci_dev *hdev)
5130{
5131 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005132
5133 hci_dev_lock(hdev);
5134
5135 /* When discoverable timeout triggers, then just make sure
5136 * the limited discoverable flag is cleared. Even in the case
5137 * of a timeout triggered from general discoverable, it is
5138 * safe to unconditionally clear the flag.
5139 */
5140 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005141 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005142
5143 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005144 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5145 u8 scan = SCAN_PAGE;
5146 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5147 sizeof(scan), &scan);
5148 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005149 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005150 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005151 hci_req_run(&req, NULL);
5152
5153 hdev->discov_timeout = 0;
5154
Johan Hedberg9a43e252013-10-20 19:00:07 +03005155 new_settings(hdev, NULL);
5156
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005157 hci_dev_unlock(hdev);
5158}
5159
Marcel Holtmann86a75642013-10-15 06:33:54 -07005160void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005161{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005162 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005163
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005164 /* Nothing needed here if there's a pending command since that
5165 * commands request completion callback takes care of everything
5166 * necessary.
5167 */
5168 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005169 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005170
Johan Hedbergbd107992014-02-24 14:52:19 +02005171 /* Powering off may clear the scan mode - don't let that interfere */
5172 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5173 return;
5174
Johan Hedberg9a43e252013-10-20 19:00:07 +03005175 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005176 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005177 } else {
5178 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005179 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005180 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005181
Johan Hedberg9a43e252013-10-20 19:00:07 +03005182 if (changed) {
5183 struct hci_request req;
5184
5185 /* In case this change in discoverable was triggered by
5186 * a disabling of connectable there could be a need to
5187 * update the advertising flags.
5188 */
5189 hci_req_init(&req, hdev);
5190 update_adv_data(&req);
5191 hci_req_run(&req, NULL);
5192
Marcel Holtmann86a75642013-10-15 06:33:54 -07005193 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005194 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005195}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005196
Marcel Holtmanna3309162013-10-15 06:33:55 -07005197void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005198{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005199 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005200
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005201 /* Nothing needed here if there's a pending command since that
5202 * commands request completion callback takes care of everything
5203 * necessary.
5204 */
5205 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005206 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005207
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005208 /* Powering off may clear the scan mode - don't let that interfere */
5209 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5210 return;
5211
Marcel Holtmanna3309162013-10-15 06:33:55 -07005212 if (connectable)
5213 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5214 else
5215 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005216
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005217 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005218 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005219}
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005220
Johan Hedberg778b2352014-02-24 14:52:17 +02005221void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5222{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005223 /* Powering off may stop advertising - don't let that interfere */
5224 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5225 return;
5226
Johan Hedberg778b2352014-02-24 14:52:17 +02005227 if (advertising)
5228 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5229 else
5230 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5231}
5232
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005233void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005234{
Johan Hedbergca69b792011-11-11 18:10:00 +02005235 u8 mgmt_err = mgmt_status(status);
5236
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005237 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005238 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005239 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005240
5241 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005242 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005243 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005244}
5245
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005246void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5247 bool persistent)
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005248{
Johan Hedberg86742e12011-11-07 23:13:38 +02005249 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005250
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005251 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005252
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005253 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005254 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005255 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005256 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005257 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005258 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005259
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005260 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca2011-01-17 14:41:05 +02005261}
Johan Hedbergf7520542011-01-20 12:34:39 +02005262
Johan Hedbergd7b25452014-05-23 13:19:53 +03005263static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5264{
5265 if (ltk->authenticated)
5266 return MGMT_LTK_AUTHENTICATED;
5267
5268 return MGMT_LTK_UNAUTHENTICATED;
5269}
5270
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005271void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005272{
5273 struct mgmt_ev_new_long_term_key ev;
5274
5275 memset(&ev, 0, sizeof(ev));
5276
Marcel Holtmann5192d302014-02-19 17:11:58 -08005277 /* Devices using resolvable or non-resolvable random addresses
5278 * without providing an indentity resolving key don't require
5279 * to store long term keys. Their addresses will change the
5280 * next time around.
5281 *
5282 * Only when a remote device provides an identity address
5283 * make sure the long term key is stored. If the remote
5284 * identity is known, the long term keys are internally
5285 * mapped to the identity address. So allow static random
5286 * and public addresses here.
5287 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005288 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5289 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5290 ev.store_hint = 0x00;
5291 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005292 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005293
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005294 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005295 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005296 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005297 ev.key.enc_size = key->enc_size;
5298 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005299 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005300
Johan Hedberg2ceba532014-06-16 19:25:16 +03005301 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005302 ev.key.master = 1;
5303
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005304 memcpy(ev.key.val, key->val, sizeof(key->val));
5305
Marcel Holtmann083368f2013-10-15 14:26:29 -07005306 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005307}
5308
Johan Hedberg95fbac82014-02-19 15:18:31 +02005309void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5310{
5311 struct mgmt_ev_new_irk ev;
5312
5313 memset(&ev, 0, sizeof(ev));
5314
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08005315 /* For identity resolving keys from devices that are already
5316 * using a public address or static random address, do not
5317 * ask for storing this key. The identity resolving key really
5318 * is only mandatory for devices using resovlable random
5319 * addresses.
5320 *
5321 * Storing all identity resolving keys has the downside that
5322 * they will be also loaded on next boot of they system. More
5323 * identity resolving keys, means more time during scanning is
5324 * needed to actually resolve these addresses.
5325 */
5326 if (bacmp(&irk->rpa, BDADDR_ANY))
5327 ev.store_hint = 0x01;
5328 else
5329 ev.store_hint = 0x00;
5330
Johan Hedberg95fbac82014-02-19 15:18:31 +02005331 bacpy(&ev.rpa, &irk->rpa);
5332 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
5333 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
5334 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
5335
5336 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
5337}
5338
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005339void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
5340 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005341{
5342 struct mgmt_ev_new_csrk ev;
5343
5344 memset(&ev, 0, sizeof(ev));
5345
5346 /* Devices using resolvable or non-resolvable random addresses
5347 * without providing an indentity resolving key don't require
5348 * to store signature resolving keys. Their addresses will change
5349 * the next time around.
5350 *
5351 * Only when a remote device provides an identity address
5352 * make sure the signature resolving key is stored. So allow
5353 * static random and public addresses here.
5354 */
5355 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5356 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
5357 ev.store_hint = 0x00;
5358 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005359 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07005360
5361 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
5362 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
5363 ev.key.master = csrk->master;
5364 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
5365
5366 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
5367}
5368
Marcel Holtmann94933992013-10-15 10:26:39 -07005369static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
5370 u8 data_len)
5371{
5372 eir[eir_len++] = sizeof(type) + data_len;
5373 eir[eir_len++] = type;
5374 memcpy(&eir[eir_len], data, data_len);
5375 eir_len += data_len;
5376
5377 return eir_len;
5378}
5379
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005380void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5381 u8 addr_type, u32 flags, u8 *name, u8 name_len,
5382 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02005383{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005384 char buf[512];
5385 struct mgmt_ev_device_connected *ev = (void *) buf;
5386 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02005387
Johan Hedbergb644ba32012-01-17 21:48:47 +02005388 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005389 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02005390
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02005391 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02005392
Johan Hedbergb644ba32012-01-17 21:48:47 +02005393 if (name_len > 0)
5394 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005395 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005396
5397 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08005398 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005399 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005400
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02005401 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005402
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07005403 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
5404 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02005405}
5406
Johan Hedberg8962ee72011-01-20 12:40:27 +02005407static void disconnect_rsp(struct pending_cmd *cmd, void *data)
5408{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01005409 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005410 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02005411 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005412
Johan Hedberg88c3df12012-02-09 14:27:38 +02005413 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5414 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005415
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005416 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005417 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005418
5419 *sk = cmd->sk;
5420 sock_hold(*sk);
5421
Johan Hedberga664b5b2011-02-19 12:06:02 -03005422 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005423}
5424
Johan Hedberg124f6e32012-02-09 13:50:12 +02005425static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02005426{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005427 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02005428 struct mgmt_cp_unpair_device *cp = cmd->param;
5429 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005430
5431 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02005432 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5433 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02005434
Johan Hedbergb1078ad2012-02-09 17:21:16 +02005435 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
5436
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005437 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02005438
5439 mgmt_pending_remove(cmd);
5440}
5441
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005442void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005443 u8 link_type, u8 addr_type, u8 reason,
5444 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02005445{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005446 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02005447 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005448 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005449
Johan Hedberg8b064a32014-02-24 14:52:22 +02005450 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5451 if (power_off) {
5452 struct mgmt_mode *cp = power_off->param;
5453
5454 /* The connection is still in hci_conn_hash so test for 1
5455 * instead of 0 to know if this is the last one.
5456 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005457 if (!cp->val && hci_conn_count(hdev) == 1) {
5458 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02005459 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005460 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02005461 }
5462
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02005463 if (!mgmt_connected)
5464 return;
5465
Andre Guedes57eb7762013-10-30 19:01:41 -03005466 if (link_type != ACL_LINK && link_type != LE_LINK)
5467 return;
5468
Johan Hedberg744cf192011-11-08 20:40:14 +02005469 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02005470
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02005471 bacpy(&ev.addr.bdaddr, bdaddr);
5472 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5473 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02005474
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07005475 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005476
5477 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01005478 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005479
Johan Hedberg124f6e32012-02-09 13:50:12 +02005480 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005481 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005482}
5483
Marcel Holtmann78929242013-10-06 23:55:47 -07005484void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
5485 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02005486{
Andre Guedes3655bba2013-10-30 19:01:40 -03005487 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
5488 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02005489 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005490 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005491
Jefferson Delfes36a75f12012-09-18 13:36:54 -04005492 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
5493 hdev);
5494
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005495 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02005496 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07005497 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02005498
Andre Guedes3655bba2013-10-30 19:01:40 -03005499 cp = cmd->param;
5500
5501 if (bacmp(bdaddr, &cp->addr.bdaddr))
5502 return;
5503
5504 if (cp->addr.type != bdaddr_type)
5505 return;
5506
Johan Hedberg88c3df12012-02-09 14:27:38 +02005507 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03005508 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02005509
Marcel Holtmann78929242013-10-06 23:55:47 -07005510 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
5511 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02005512
Johan Hedberga664b5b2011-02-19 12:06:02 -03005513 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02005514}
Johan Hedberg17d5c042011-01-22 06:09:08 +02005515
Marcel Holtmann445608d2013-10-06 23:55:48 -07005516void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5517 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02005518{
5519 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02005520 struct pending_cmd *power_off;
5521
5522 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5523 if (power_off) {
5524 struct mgmt_mode *cp = power_off->param;
5525
5526 /* The connection is still in hci_conn_hash so test for 1
5527 * instead of 0 to know if this is the last one.
5528 */
Johan Hedberga3172b72014-02-28 09:33:44 +02005529 if (!cp->val && hci_conn_count(hdev) == 1) {
5530 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02005531 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02005532 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02005533 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02005534
Johan Hedberg4c659c32011-11-07 23:13:39 +02005535 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005536 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005537 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005538
Marcel Holtmann445608d2013-10-06 23:55:48 -07005539 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02005540}
Johan Hedberg980e1a52011-01-22 06:10:07 +02005541
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005542void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005543{
5544 struct mgmt_ev_pin_code_request ev;
5545
Johan Hedbergd8457692012-02-17 14:24:57 +02005546 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005547 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02005548 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005549
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07005550 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005551}
5552
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005553void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5554 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005555{
5556 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005557 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005558
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005559 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005560 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005561 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005562
Johan Hedbergd8457692012-02-17 14:24:57 +02005563 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005564 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005565
Marcel Holtmanne669cf82013-10-15 14:26:21 -07005566 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
5567 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005568
Johan Hedberga664b5b2011-02-19 12:06:02 -03005569 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005570}
5571
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005572void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
5573 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02005574{
5575 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005576 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005577
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005578 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005579 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005580 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02005581
Johan Hedbergd8457692012-02-17 14:24:57 +02005582 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005583 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03005584
Marcel Holtmann3eb38522013-10-15 14:26:22 -07005585 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
5586 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02005587
Johan Hedberga664b5b2011-02-19 12:06:02 -03005588 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02005589}
Johan Hedberga5c29682011-02-19 12:05:57 -03005590
Johan Hedberg744cf192011-11-08 20:40:14 +02005591int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02005592 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005593 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03005594{
5595 struct mgmt_ev_user_confirm_request ev;
5596
Johan Hedberg744cf192011-11-08 20:40:14 +02005597 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03005598
Johan Hedberg272d90d2012-02-09 15:26:12 +02005599 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005600 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07005601 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02005602 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03005603
Johan Hedberg744cf192011-11-08 20:40:14 +02005604 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005605 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03005606}
5607
Johan Hedberg272d90d2012-02-09 15:26:12 +02005608int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005609 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08005610{
5611 struct mgmt_ev_user_passkey_request ev;
5612
5613 BT_DBG("%s", hdev->name);
5614
Johan Hedberg272d90d2012-02-09 15:26:12 +02005615 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005616 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08005617
5618 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005619 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08005620}
5621
Brian Gix0df4c182011-11-16 13:53:13 -08005622static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005623 u8 link_type, u8 addr_type, u8 status,
5624 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03005625{
5626 struct pending_cmd *cmd;
5627 struct mgmt_rp_user_confirm_reply rp;
5628 int err;
5629
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005630 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03005631 if (!cmd)
5632 return -ENOENT;
5633
Johan Hedberg272d90d2012-02-09 15:26:12 +02005634 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005635 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02005636 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005637 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03005638
Johan Hedberga664b5b2011-02-19 12:06:02 -03005639 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03005640
5641 return err;
5642}
5643
Johan Hedberg744cf192011-11-08 20:40:14 +02005644int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005645 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005646{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005647 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005648 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005649}
5650
Johan Hedberg272d90d2012-02-09 15:26:12 +02005651int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005652 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03005653{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005654 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005655 status,
5656 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03005657}
Johan Hedberg2a611692011-02-19 12:06:00 -03005658
Brian Gix604086b2011-11-23 08:28:33 -08005659int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005660 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005661{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005662 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005663 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005664}
5665
Johan Hedberg272d90d2012-02-09 15:26:12 +02005666int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005667 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08005668{
Johan Hedberg272d90d2012-02-09 15:26:12 +02005669 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03005670 status,
5671 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08005672}
5673
Johan Hedberg92a25252012-09-06 18:39:26 +03005674int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
5675 u8 link_type, u8 addr_type, u32 passkey,
5676 u8 entered)
5677{
5678 struct mgmt_ev_passkey_notify ev;
5679
5680 BT_DBG("%s", hdev->name);
5681
5682 bacpy(&ev.addr.bdaddr, bdaddr);
5683 ev.addr.type = link_to_bdaddr(link_type, addr_type);
5684 ev.passkey = __cpu_to_le32(passkey);
5685 ev.entered = entered;
5686
5687 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
5688}
5689
Marcel Holtmanne5460992013-10-15 14:26:23 -07005690void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5691 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03005692{
5693 struct mgmt_ev_auth_failed ev;
5694
Johan Hedbergbab73cb2012-02-09 16:07:29 +02005695 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005696 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02005697 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03005698
Marcel Holtmanne5460992013-10-15 14:26:23 -07005699 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03005700}
Johan Hedbergb312b1612011-03-16 14:29:37 +02005701
Marcel Holtmann464996a2013-10-15 14:26:24 -07005702void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005703{
5704 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07005705 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005706
5707 if (status) {
5708 u8 mgmt_err = mgmt_status(status);
5709 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005710 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07005711 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005712 }
5713
Marcel Holtmann464996a2013-10-15 14:26:24 -07005714 if (test_bit(HCI_AUTH, &hdev->flags))
5715 changed = !test_and_set_bit(HCI_LINK_SECURITY,
5716 &hdev->dev_flags);
5717 else
5718 changed = test_and_clear_bit(HCI_LINK_SECURITY,
5719 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02005720
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005721 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005722 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005723
Johan Hedberg47990ea2012-02-22 11:58:37 +02005724 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07005725 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005726
5727 if (match.sk)
5728 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02005729}
5730
Johan Hedberg890ea892013-03-15 17:06:52 -05005731static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02005732{
Johan Hedberg890ea892013-03-15 17:06:52 -05005733 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005734 struct hci_cp_write_eir cp;
5735
Johan Hedberg976eb202012-10-24 21:12:01 +03005736 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005737 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02005738
Johan Hedbergc80da272012-02-22 15:38:48 +02005739 memset(hdev->eir, 0, sizeof(hdev->eir));
5740
Johan Hedbergcacaf522012-02-21 00:52:42 +02005741 memset(&cp, 0, sizeof(cp));
5742
Johan Hedberg890ea892013-03-15 17:06:52 -05005743 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02005744}
5745
Marcel Holtmann3e248562013-10-15 14:26:25 -07005746void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005747{
5748 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05005749 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005750 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005751
5752 if (status) {
5753 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005754
5755 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005756 &hdev->dev_flags)) {
5757 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005758 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005759 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005760
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005761 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
5762 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07005763 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005764 }
5765
5766 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005767 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005768 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07005769 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
5770 if (!changed)
5771 changed = test_and_clear_bit(HCI_HS_ENABLED,
5772 &hdev->dev_flags);
5773 else
5774 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005775 }
5776
5777 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
5778
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02005779 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07005780 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005781
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005782 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005783 sock_put(match.sk);
5784
Johan Hedberg890ea892013-03-15 17:06:52 -05005785 hci_req_init(&req, hdev);
5786
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005787 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005788 update_eir(&req);
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02005789 else
Johan Hedberg890ea892013-03-15 17:06:52 -05005790 clear_eir(&req);
5791
5792 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02005793}
5794
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005795void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
5796{
5797 struct cmd_lookup match = { NULL, hdev };
5798 bool changed = false;
5799
5800 if (status) {
5801 u8 mgmt_err = mgmt_status(status);
5802
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005803 if (enable) {
5804 if (test_and_clear_bit(HCI_SC_ENABLED,
5805 &hdev->dev_flags))
5806 new_settings(hdev, NULL);
5807 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5808 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005809
5810 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5811 cmd_status_rsp, &mgmt_err);
5812 return;
5813 }
5814
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005815 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005816 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005817 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005818 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005819 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
5820 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005821
5822 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
5823 settings_rsp, &match);
5824
5825 if (changed)
5826 new_settings(hdev, match.sk);
5827
5828 if (match.sk)
5829 sock_put(match.sk);
5830}
5831
Johan Hedberg92da6092013-03-15 17:06:55 -05005832static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02005833{
5834 struct cmd_lookup *match = data;
5835
Johan Hedberg90e70452012-02-23 23:09:40 +02005836 if (match->sk == NULL) {
5837 match->sk = cmd->sk;
5838 sock_hold(match->sk);
5839 }
Johan Hedberg90e70452012-02-23 23:09:40 +02005840}
5841
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005842void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
5843 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005844{
Johan Hedberg90e70452012-02-23 23:09:40 +02005845 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005846
Johan Hedberg92da6092013-03-15 17:06:55 -05005847 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
5848 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
5849 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02005850
5851 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07005852 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
5853 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02005854
5855 if (match.sk)
5856 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01005857}
5858
Marcel Holtmann7667da32013-10-15 14:26:27 -07005859void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02005860{
Johan Hedbergb312b1612011-03-16 14:29:37 +02005861 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05005862 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005863
Johan Hedberg13928972013-03-15 17:07:00 -05005864 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07005865 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005866
5867 memset(&ev, 0, sizeof(ev));
5868 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02005869 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005870
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005871 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05005872 if (!cmd) {
5873 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02005874
Johan Hedberg13928972013-03-15 17:07:00 -05005875 /* If this is a HCI command related to powering on the
5876 * HCI dev don't send any mgmt signals.
5877 */
5878 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07005879 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02005880 }
5881
Marcel Holtmann7667da32013-10-15 14:26:27 -07005882 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
5883 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02005884}
Szymon Jancc35938b2011-03-22 13:12:21 +01005885
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005886void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
5887 u8 *randomizer192, u8 *hash256,
5888 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01005889{
5890 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01005891
Johan Hedberg744cf192011-11-08 20:40:14 +02005892 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01005893
Johan Hedberg2e58ef32011-11-08 20:40:15 +02005894 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01005895 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005896 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01005897
5898 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07005899 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
5900 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01005901 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005902 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
5903 hash256 && randomizer256) {
5904 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01005905
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005906 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
5907 memcpy(rp.randomizer192, randomizer192,
5908 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01005909
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08005910 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
5911 memcpy(rp.randomizer256, randomizer256,
5912 sizeof(rp.randomizer256));
5913
5914 cmd_complete(cmd->sk, hdev->id,
5915 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5916 &rp, sizeof(rp));
5917 } else {
5918 struct mgmt_rp_read_local_oob_data rp;
5919
5920 memcpy(rp.hash, hash192, sizeof(rp.hash));
5921 memcpy(rp.randomizer, randomizer192,
5922 sizeof(rp.randomizer));
5923
5924 cmd_complete(cmd->sk, hdev->id,
5925 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
5926 &rp, sizeof(rp));
5927 }
Szymon Jancc35938b2011-03-22 13:12:21 +01005928 }
5929
5930 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01005931}
Johan Hedberge17acd42011-03-30 23:57:16 +03005932
Marcel Holtmann901801b2013-10-06 23:55:51 -07005933void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Johan Hedberg73cf71d2014-03-25 12:06:19 +02005934 u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
5935 u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp,
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005936 u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03005937{
Johan Hedberge319d2e2012-01-15 19:51:59 +02005938 char buf[512];
5939 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005940 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02005941 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03005942
Andre Guedes12602d02013-04-30 15:29:40 -03005943 if (!hci_discovery_active(hdev))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005944 return;
Andre Guedes12602d02013-04-30 15:29:40 -03005945
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005946 /* Make sure that the buffer is big enough. The 5 extra bytes
5947 * are for the potential CoD field.
5948 */
5949 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07005950 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03005951
Johan Hedberg1dc06092012-01-15 21:01:23 +02005952 memset(buf, 0, sizeof(buf));
5953
Johan Hedberg5cedbb82014-02-18 21:41:37 +02005954 irk = hci_get_irk(hdev, bdaddr, addr_type);
5955 if (irk) {
5956 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
5957 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
5958 } else {
5959 bacpy(&ev->addr.bdaddr, bdaddr);
5960 ev->addr.type = link_to_bdaddr(link_type, addr_type);
5961 }
5962
Johan Hedberge319d2e2012-01-15 19:51:59 +02005963 ev->rssi = rssi;
Johan Hedberg9a395a82012-02-23 00:00:32 +02005964 if (cfm_name)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005965 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME);
Johan Hedberg388fc8f2012-02-23 00:38:59 +02005966 if (!ssp)
Joe Perchesdcf4adb2014-03-12 10:52:35 -07005967 ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING);
Johan Hedberge17acd42011-03-30 23:57:16 +03005968
Johan Hedberg1dc06092012-01-15 21:01:23 +02005969 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02005970 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03005971
Johan Hedberg1dc06092012-01-15 21:01:23 +02005972 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
5973 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005974 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02005975
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02005976 if (scan_rsp_len > 0)
5977 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
5978
5979 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
5980 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03005981
Marcel Holtmann901801b2013-10-06 23:55:51 -07005982 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03005983}
Johan Hedberga88a9652011-03-30 13:18:12 +03005984
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07005985void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
5986 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03005987{
Johan Hedbergb644ba32012-01-17 21:48:47 +02005988 struct mgmt_ev_device_found *ev;
5989 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
5990 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03005991
Johan Hedbergb644ba32012-01-17 21:48:47 +02005992 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03005993
Johan Hedbergb644ba32012-01-17 21:48:47 +02005994 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03005995
Johan Hedbergb644ba32012-01-17 21:48:47 +02005996 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005997 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02005998 ev->rssi = rssi;
5999
6000 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006001 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006002
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006003 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006004
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006005 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006006}
Johan Hedberg314b2382011-04-27 10:29:57 -04006007
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006008void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006009{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006010 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006011 struct pending_cmd *cmd;
6012
Andre Guedes343fb142011-11-22 17:14:19 -03006013 BT_DBG("%s discovering %u", hdev->name, discovering);
6014
Johan Hedberg164a6e72011-11-01 17:06:44 +02006015 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006016 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006017 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006018 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006019
6020 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006021 u8 type = hdev->discovery.type;
6022
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006023 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6024 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006025 mgmt_pending_remove(cmd);
6026 }
6027
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006028 memset(&ev, 0, sizeof(ev));
6029 ev.type = hdev->discovery.type;
6030 ev.discovering = discovering;
6031
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006032 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006033}
Antti Julku5e762442011-08-25 16:48:02 +03006034
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006035int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006036{
6037 struct pending_cmd *cmd;
6038 struct mgmt_ev_device_blocked ev;
6039
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006040 cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006041
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006042 bacpy(&ev.addr.bdaddr, bdaddr);
6043 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006044
Johan Hedberg744cf192011-11-08 20:40:14 +02006045 return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006046 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006047}
6048
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006049int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
Antti Julku5e762442011-08-25 16:48:02 +03006050{
6051 struct pending_cmd *cmd;
6052 struct mgmt_ev_device_unblocked ev;
6053
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006054 cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev);
Antti Julku5e762442011-08-25 16:48:02 +03006055
Johan Hedberg88c1fe42012-02-09 15:56:11 +02006056 bacpy(&ev.addr.bdaddr, bdaddr);
6057 ev.addr.type = type;
Antti Julku5e762442011-08-25 16:48:02 +03006058
Johan Hedberg744cf192011-11-08 20:40:14 +02006059 return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006060 cmd ? cmd->sk : NULL);
Antti Julku5e762442011-08-25 16:48:02 +03006061}
Marcel Holtmann5976e602013-10-06 04:08:14 -07006062
6063static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6064{
6065 BT_DBG("%s status %u", hdev->name, status);
6066
6067 /* Clear the advertising mgmt setting if we failed to re-enable it */
6068 if (status) {
6069 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006070 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006071 }
6072}
6073
6074void mgmt_reenable_advertising(struct hci_dev *hdev)
6075{
6076 struct hci_request req;
6077
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006078 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006079 return;
6080
6081 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6082 return;
6083
6084 hci_req_init(&req, hdev);
6085 enable_advertising(&req);
6086
6087 /* If this fails we have no option but to let user space know
6088 * that we've disabled advertising.
6089 */
6090 if (hci_req_run(&req, adv_enable_complete) < 0) {
6091 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006092 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006093 }
6094}