blob: 04a66429ad4db3aea8a6703e84fa5619bdcbef7c [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann730f0912014-06-28 12:36:10 +020038#define MGMT_REVISION 7
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
47 MGMT_OP_SET_PAIRABLE,
48 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020095};
96
97static const u16 mgmt_events[] = {
98 MGMT_EV_CONTROLLER_ERROR,
99 MGMT_EV_INDEX_ADDED,
100 MGMT_EV_INDEX_REMOVED,
101 MGMT_EV_NEW_SETTINGS,
102 MGMT_EV_CLASS_OF_DEV_CHANGED,
103 MGMT_EV_LOCAL_NAME_CHANGED,
104 MGMT_EV_NEW_LINK_KEY,
105 MGMT_EV_NEW_LONG_TERM_KEY,
106 MGMT_EV_DEVICE_CONNECTED,
107 MGMT_EV_DEVICE_DISCONNECTED,
108 MGMT_EV_CONNECT_FAILED,
109 MGMT_EV_PIN_CODE_REQUEST,
110 MGMT_EV_USER_CONFIRM_REQUEST,
111 MGMT_EV_USER_PASSKEY_REQUEST,
112 MGMT_EV_AUTH_FAILED,
113 MGMT_EV_DEVICE_FOUND,
114 MGMT_EV_DISCOVERING,
115 MGMT_EV_DEVICE_BLOCKED,
116 MGMT_EV_DEVICE_UNBLOCKED,
117 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300118 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800119 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700120 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200121 MGMT_EV_DEVICE_ADDED,
122 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300123 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200124 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd3896b2014-07-02 21:30:55 +0200125 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200126 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200127};
128
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800129#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200130
Johan Hedberg4b34ee782012-02-21 14:13:02 +0200131#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
132 !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
133
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200134struct pending_cmd {
135 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200136 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100138 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141};
142
Johan Hedbergca69b792011-11-11 18:10:00 +0200143/* HCI to MGMT error code conversion table */
144static u8 mgmt_status_table[] = {
145 MGMT_STATUS_SUCCESS,
146 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
147 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
148 MGMT_STATUS_FAILED, /* Hardware Failure */
149 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
150 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200151 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200152 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
153 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
154 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
156 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
157 MGMT_STATUS_BUSY, /* Command Disallowed */
158 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
159 MGMT_STATUS_REJECTED, /* Rejected Security */
160 MGMT_STATUS_REJECTED, /* Rejected Personal */
161 MGMT_STATUS_TIMEOUT, /* Host Timeout */
162 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
163 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
164 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
165 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
166 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
167 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
168 MGMT_STATUS_BUSY, /* Repeated Attempts */
169 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
170 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
171 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
172 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
173 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
174 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
175 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
176 MGMT_STATUS_FAILED, /* Unspecified Error */
177 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
178 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
179 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
180 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
181 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
182 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
183 MGMT_STATUS_FAILED, /* Unit Link Key Used */
184 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
185 MGMT_STATUS_TIMEOUT, /* Instant Passed */
186 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
187 MGMT_STATUS_FAILED, /* Transaction Collision */
188 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
189 MGMT_STATUS_REJECTED, /* QoS Rejected */
190 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
191 MGMT_STATUS_REJECTED, /* Insufficient Security */
192 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
193 MGMT_STATUS_BUSY, /* Role Switch Pending */
194 MGMT_STATUS_FAILED, /* Slot Violation */
195 MGMT_STATUS_FAILED, /* Role Switch Failed */
196 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
197 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
198 MGMT_STATUS_BUSY, /* Host Busy Pairing */
199 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
200 MGMT_STATUS_BUSY, /* Controller Busy */
201 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
202 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
203 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
204 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
205 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
206};
207
208static u8 mgmt_status(u8 hci_status)
209{
210 if (hci_status < ARRAY_SIZE(mgmt_status_table))
211 return mgmt_status_table[hci_status];
212
213 return MGMT_STATUS_FAILED;
214}
215
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200216static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
217 struct sock *skip_sk)
218{
219 struct sk_buff *skb;
220 struct mgmt_hdr *hdr;
221
222 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
223 if (!skb)
224 return -ENOMEM;
225
226 hdr = (void *) skb_put(skb, sizeof(*hdr));
227 hdr->opcode = cpu_to_le16(event);
228 if (hdev)
229 hdr->index = cpu_to_le16(hdev->id);
230 else
231 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
232 hdr->len = cpu_to_le16(data_len);
233
234 if (data)
235 memcpy(skb_put(skb, data_len), data, data_len);
236
237 /* Time stamp */
238 __net_timestamp(skb);
239
240 hci_send_to_control(skb, skip_sk);
241 kfree_skb(skb);
242
243 return 0;
244}
245
Szymon Janc4e51eae2011-02-25 19:05:48 +0100246static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200247{
248 struct sk_buff *skb;
249 struct mgmt_hdr *hdr;
250 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300251 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200252
Szymon Janc34eb5252011-02-28 14:10:08 +0100253 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200254
Andre Guedes790eff42012-06-07 19:05:46 -0300255 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200256 if (!skb)
257 return -ENOMEM;
258
259 hdr = (void *) skb_put(skb, sizeof(*hdr));
260
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700261 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100262 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200263 hdr->len = cpu_to_le16(sizeof(*ev));
264
265 ev = (void *) skb_put(skb, sizeof(*ev));
266 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200267 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200268
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300269 err = sock_queue_rcv_skb(sk, skb);
270 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200271 kfree_skb(skb);
272
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300273 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200274}
275
Johan Hedbergaee9b212012-02-18 15:07:59 +0200276static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300277 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200278{
279 struct sk_buff *skb;
280 struct mgmt_hdr *hdr;
281 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300282 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200283
284 BT_DBG("sock %p", sk);
285
Andre Guedes790eff42012-06-07 19:05:46 -0300286 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200287 if (!skb)
288 return -ENOMEM;
289
290 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200291
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700292 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100293 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200294 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200295
Johan Hedberga38528f2011-01-22 06:46:43 +0200296 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200297 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200298 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100299
300 if (rp)
301 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200302
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300303 err = sock_queue_rcv_skb(sk, skb);
304 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200305 kfree_skb(skb);
306
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100307 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200308}
309
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300310static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
311 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200312{
313 struct mgmt_rp_read_version rp;
314
315 BT_DBG("sock %p", sk);
316
317 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700318 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200319
Johan Hedbergaee9b212012-02-18 15:07:59 +0200320 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300321 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200322}
323
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300324static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
325 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200326{
327 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200328 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
329 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200330 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200331 size_t rp_size;
332 int i, err;
333
334 BT_DBG("sock %p", sk);
335
336 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
337
338 rp = kmalloc(rp_size, GFP_KERNEL);
339 if (!rp)
340 return -ENOMEM;
341
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700342 rp->num_commands = cpu_to_le16(num_commands);
343 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200344
345 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
346 put_unaligned_le16(mgmt_commands[i], opcode);
347
348 for (i = 0; i < num_events; i++, opcode++)
349 put_unaligned_le16(mgmt_events[i], opcode);
350
Johan Hedbergaee9b212012-02-18 15:07:59 +0200351 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300352 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200353 kfree(rp);
354
355 return err;
356}
357
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300358static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
359 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200360{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200362 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200363 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200364 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300365 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366
367 BT_DBG("sock %p", sk);
368
369 read_lock(&hci_dev_list_lock);
370
371 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300372 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200373 if (d->dev_type == HCI_BREDR &&
374 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700375 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200376 }
377
Johan Hedberga38528f2011-01-22 06:46:43 +0200378 rp_len = sizeof(*rp) + (2 * count);
379 rp = kmalloc(rp_len, GFP_ATOMIC);
380 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100381 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200382 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100383 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200384
Johan Hedberg476e44c2012-10-19 20:10:46 +0300385 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200386 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200387 if (test_bit(HCI_SETUP, &d->dev_flags) ||
388 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200389 continue;
390
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200391 /* Devices marked as raw-only are neither configured
392 * nor unconfigured controllers.
393 */
394 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700395 continue;
396
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200397 if (d->dev_type == HCI_BREDR &&
398 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700399 rp->index[count++] = cpu_to_le16(d->id);
400 BT_DBG("Added hci%u", d->id);
401 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200402 }
403
Johan Hedberg476e44c2012-10-19 20:10:46 +0300404 rp->num_controllers = cpu_to_le16(count);
405 rp_len = sizeof(*rp) + (2 * count);
406
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200407 read_unlock(&hci_dev_list_lock);
408
Johan Hedbergaee9b212012-02-18 15:07:59 +0200409 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300410 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200411
Johan Hedberga38528f2011-01-22 06:46:43 +0200412 kfree(rp);
413
414 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200415}
416
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200417static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
418 void *data, u16 data_len)
419{
420 struct mgmt_rp_read_unconf_index_list *rp;
421 struct hci_dev *d;
422 size_t rp_len;
423 u16 count;
424 int err;
425
426 BT_DBG("sock %p", sk);
427
428 read_lock(&hci_dev_list_lock);
429
430 count = 0;
431 list_for_each_entry(d, &hci_dev_list, list) {
432 if (d->dev_type == HCI_BREDR &&
433 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
434 count++;
435 }
436
437 rp_len = sizeof(*rp) + (2 * count);
438 rp = kmalloc(rp_len, GFP_ATOMIC);
439 if (!rp) {
440 read_unlock(&hci_dev_list_lock);
441 return -ENOMEM;
442 }
443
444 count = 0;
445 list_for_each_entry(d, &hci_dev_list, list) {
446 if (test_bit(HCI_SETUP, &d->dev_flags) ||
447 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
448 continue;
449
450 /* Devices marked as raw-only are neither configured
451 * nor unconfigured controllers.
452 */
453 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
454 continue;
455
456 if (d->dev_type == HCI_BREDR &&
457 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
458 rp->index[count++] = cpu_to_le16(d->id);
459 BT_DBG("Added hci%u", d->id);
460 }
461 }
462
463 rp->num_controllers = cpu_to_le16(count);
464 rp_len = sizeof(*rp) + (2 * count);
465
466 read_unlock(&hci_dev_list_lock);
467
468 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
469 0, rp, rp_len);
470
471 kfree(rp);
472
473 return err;
474}
475
Marcel Holtmanndbece372014-07-04 18:11:55 +0200476static bool is_configured(struct hci_dev *hdev)
477{
478 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
479 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
480 return false;
481
482 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
483 !bacmp(&hdev->public_addr, BDADDR_ANY))
484 return false;
485
486 return true;
487}
488
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200489static __le32 get_missing_options(struct hci_dev *hdev)
490{
491 u32 options = 0;
492
Marcel Holtmanndbece372014-07-04 18:11:55 +0200493 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
494 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200495 options |= MGMT_OPTION_EXTERNAL_CONFIG;
496
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200497 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
498 !bacmp(&hdev->public_addr, BDADDR_ANY))
499 options |= MGMT_OPTION_PUBLIC_ADDRESS;
500
501 return cpu_to_le32(options);
502}
503
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200504static int new_options(struct hci_dev *hdev, struct sock *skip)
505{
506 __le32 options = get_missing_options(hdev);
507
508 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
509 sizeof(options), skip);
510}
511
Marcel Holtmanndbece372014-07-04 18:11:55 +0200512static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
513{
514 __le32 options = get_missing_options(hdev);
515
516 return cmd_complete(sk, hdev->id, opcode, 0, &options,
517 sizeof(options));
518}
519
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200520static int read_config_info(struct sock *sk, struct hci_dev *hdev,
521 void *data, u16 data_len)
522{
523 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200524 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200525
526 BT_DBG("sock %p %s", sk, hdev->name);
527
528 hci_dev_lock(hdev);
529
530 memset(&rp, 0, sizeof(rp));
531 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200533 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
534 options |= MGMT_OPTION_EXTERNAL_CONFIG;
535
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200536 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200537 options |= MGMT_OPTION_PUBLIC_ADDRESS;
538
539 rp.supported_options = cpu_to_le32(options);
540 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200541
542 hci_dev_unlock(hdev);
543
544 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
545 sizeof(rp));
546}
547
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200548static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200549{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200550 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200551
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200552 settings |= MGMT_SETTING_POWERED;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 settings |= MGMT_SETTING_PAIRABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800554 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg03811012010-12-08 00:21:06 +0200555
Andre Guedesed3fa312012-07-24 15:03:46 -0300556 if (lmp_bredr_capable(hdev)) {
Johan Hedberg33c525c2012-10-24 21:11:58 +0300557 settings |= MGMT_SETTING_CONNECTABLE;
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500558 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
559 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg33c525c2012-10-24 21:11:58 +0300560 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200561 settings |= MGMT_SETTING_BREDR;
562 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700563
564 if (lmp_ssp_capable(hdev)) {
565 settings |= MGMT_SETTING_SSP;
566 settings |= MGMT_SETTING_HS;
567 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800568
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800569 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200570 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700572 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100573
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300574 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200575 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300576 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200577 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300578 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200579
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200580 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
581 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200582 settings |= MGMT_SETTING_CONFIGURATION;
583
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200584 return settings;
585}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587static u32 get_current_settings(struct hci_dev *hdev)
588{
589 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200590
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200591 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100592 settings |= MGMT_SETTING_POWERED;
593
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200594 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200595 settings |= MGMT_SETTING_CONNECTABLE;
596
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500597 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
598 settings |= MGMT_SETTING_FAST_CONNECTABLE;
599
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200600 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200601 settings |= MGMT_SETTING_DISCOVERABLE;
602
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200603 if (test_bit(HCI_PAIRABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_PAIRABLE;
605
Johan Hedberg56f87902013-10-02 13:43:13 +0300606 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200607 settings |= MGMT_SETTING_BREDR;
608
Johan Hedberg06199cf2012-02-22 16:37:11 +0200609 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200611
Johan Hedberg47990ea2012-02-22 11:58:37 +0200612 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200614
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200615 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200617
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200618 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
619 settings |= MGMT_SETTING_HS;
620
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200621 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300622 settings |= MGMT_SETTING_ADVERTISING;
623
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800624 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
625 settings |= MGMT_SETTING_SECURE_CONN;
626
Johan Hedberg0663b292014-06-24 13:15:50 +0300627 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800628 settings |= MGMT_SETTING_DEBUG_KEYS;
629
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200630 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
631 settings |= MGMT_SETTING_PRIVACY;
632
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200634}
635
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300636#define PNP_INFO_SVCLASS_ID 0x1200
637
Johan Hedberg213202e2013-01-27 00:31:33 +0200638static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
639{
640 u8 *ptr = data, *uuids_start = NULL;
641 struct bt_uuid *uuid;
642
643 if (len < 4)
644 return ptr;
645
646 list_for_each_entry(uuid, &hdev->uuids, list) {
647 u16 uuid16;
648
649 if (uuid->size != 16)
650 continue;
651
652 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
653 if (uuid16 < 0x1100)
654 continue;
655
656 if (uuid16 == PNP_INFO_SVCLASS_ID)
657 continue;
658
659 if (!uuids_start) {
660 uuids_start = ptr;
661 uuids_start[0] = 1;
662 uuids_start[1] = EIR_UUID16_ALL;
663 ptr += 2;
664 }
665
666 /* Stop if not enough space to put next UUID */
667 if ((ptr - data) + sizeof(u16) > len) {
668 uuids_start[1] = EIR_UUID16_SOME;
669 break;
670 }
671
672 *ptr++ = (uuid16 & 0x00ff);
673 *ptr++ = (uuid16 & 0xff00) >> 8;
674 uuids_start[0] += sizeof(uuid16);
675 }
676
677 return ptr;
678}
679
Johan Hedbergcdf19632013-01-27 00:31:34 +0200680static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
681{
682 u8 *ptr = data, *uuids_start = NULL;
683 struct bt_uuid *uuid;
684
685 if (len < 6)
686 return ptr;
687
688 list_for_each_entry(uuid, &hdev->uuids, list) {
689 if (uuid->size != 32)
690 continue;
691
692 if (!uuids_start) {
693 uuids_start = ptr;
694 uuids_start[0] = 1;
695 uuids_start[1] = EIR_UUID32_ALL;
696 ptr += 2;
697 }
698
699 /* Stop if not enough space to put next UUID */
700 if ((ptr - data) + sizeof(u32) > len) {
701 uuids_start[1] = EIR_UUID32_SOME;
702 break;
703 }
704
705 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
706 ptr += sizeof(u32);
707 uuids_start[0] += sizeof(u32);
708 }
709
710 return ptr;
711}
712
Johan Hedbergc00d5752013-01-27 00:31:35 +0200713static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
714{
715 u8 *ptr = data, *uuids_start = NULL;
716 struct bt_uuid *uuid;
717
718 if (len < 18)
719 return ptr;
720
721 list_for_each_entry(uuid, &hdev->uuids, list) {
722 if (uuid->size != 128)
723 continue;
724
725 if (!uuids_start) {
726 uuids_start = ptr;
727 uuids_start[0] = 1;
728 uuids_start[1] = EIR_UUID128_ALL;
729 ptr += 2;
730 }
731
732 /* Stop if not enough space to put next UUID */
733 if ((ptr - data) + 16 > len) {
734 uuids_start[1] = EIR_UUID128_SOME;
735 break;
736 }
737
738 memcpy(ptr, uuid->uuid, 16);
739 ptr += 16;
740 uuids_start[0] += 16;
741 }
742
743 return ptr;
744}
745
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300746static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
747{
748 struct pending_cmd *cmd;
749
750 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
751 if (cmd->opcode == opcode)
752 return cmd;
753 }
754
755 return NULL;
756}
757
Johan Hedberg95868422014-06-28 17:54:07 +0300758static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
759 struct hci_dev *hdev,
760 const void *data)
761{
762 struct pending_cmd *cmd;
763
764 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
765 if (cmd->user_data != data)
766 continue;
767 if (cmd->opcode == opcode)
768 return cmd;
769 }
770
771 return NULL;
772}
773
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700774static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
775{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700776 u8 ad_len = 0;
777 size_t name_len;
778
779 name_len = strlen(hdev->dev_name);
780 if (name_len > 0) {
781 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
782
783 if (name_len > max_len) {
784 name_len = max_len;
785 ptr[1] = EIR_NAME_SHORT;
786 } else
787 ptr[1] = EIR_NAME_COMPLETE;
788
789 ptr[0] = name_len + 1;
790
791 memcpy(ptr + 2, hdev->dev_name, name_len);
792
793 ad_len += (name_len + 2);
794 ptr += (name_len + 2);
795 }
796
797 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700798}
799
800static void update_scan_rsp_data(struct hci_request *req)
801{
802 struct hci_dev *hdev = req->hdev;
803 struct hci_cp_le_set_scan_rsp_data cp;
804 u8 len;
805
Johan Hedberg7751ef12013-10-19 23:38:15 +0300806 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700807 return;
808
809 memset(&cp, 0, sizeof(cp));
810
811 len = create_scan_rsp_data(hdev, cp.data);
812
Johan Hedbergeb438b52013-10-16 15:31:07 +0300813 if (hdev->scan_rsp_data_len == len &&
814 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700815 return;
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
818 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819
820 cp.length = len;
821
822 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
823}
824
Johan Hedberg9a43e252013-10-20 19:00:07 +0300825static u8 get_adv_discov_flags(struct hci_dev *hdev)
826{
827 struct pending_cmd *cmd;
828
829 /* If there's a pending mgmt command the flags will not yet have
830 * their final values, so check for this first.
831 */
832 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
833 if (cmd) {
834 struct mgmt_mode *cp = cmd->param;
835 if (cp->val == 0x01)
836 return LE_AD_GENERAL;
837 else if (cp->val == 0x02)
838 return LE_AD_LIMITED;
839 } else {
840 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
841 return LE_AD_LIMITED;
842 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
843 return LE_AD_GENERAL;
844 }
845
846 return 0;
847}
848
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700849static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700850{
851 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700852
Johan Hedberg9a43e252013-10-20 19:00:07 +0300853 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854
Johan Hedberge8340042014-01-30 11:16:50 -0800855 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
858 if (flags) {
859 BT_DBG("adv flags 0x%02x", flags);
860
861 ptr[0] = 2;
862 ptr[1] = EIR_FLAGS;
863 ptr[2] = flags;
864
865 ad_len += 3;
866 ptr += 3;
867 }
868
869 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
870 ptr[0] = 2;
871 ptr[1] = EIR_TX_POWER;
872 ptr[2] = (u8) hdev->adv_tx_power;
873
874 ad_len += 3;
875 ptr += 3;
876 }
877
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700878 return ad_len;
879}
880
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700881static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882{
883 struct hci_dev *hdev = req->hdev;
884 struct hci_cp_le_set_adv_data cp;
885 u8 len;
886
Johan Hedberg10994ce2013-10-19 23:38:16 +0300887 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700888 return;
889
890 memset(&cp, 0, sizeof(cp));
891
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700892 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893
894 if (hdev->adv_data_len == len &&
895 memcmp(cp.data, hdev->adv_data, len) == 0)
896 return;
897
898 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
899 hdev->adv_data_len = len;
900
901 cp.length = len;
902
903 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
904}
905
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300906static void create_eir(struct hci_dev *hdev, u8 *data)
907{
908 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300909 size_t name_len;
910
911 name_len = strlen(hdev->dev_name);
912
913 if (name_len > 0) {
914 /* EIR Data type */
915 if (name_len > 48) {
916 name_len = 48;
917 ptr[1] = EIR_NAME_SHORT;
918 } else
919 ptr[1] = EIR_NAME_COMPLETE;
920
921 /* EIR Data length */
922 ptr[0] = name_len + 1;
923
924 memcpy(ptr + 2, hdev->dev_name, name_len);
925
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300926 ptr += (name_len + 2);
927 }
928
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100929 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700930 ptr[0] = 2;
931 ptr[1] = EIR_TX_POWER;
932 ptr[2] = (u8) hdev->inq_tx_power;
933
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700934 ptr += 3;
935 }
936
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700937 if (hdev->devid_source > 0) {
938 ptr[0] = 9;
939 ptr[1] = EIR_DEVICE_ID;
940
941 put_unaligned_le16(hdev->devid_source, ptr + 2);
942 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
943 put_unaligned_le16(hdev->devid_product, ptr + 6);
944 put_unaligned_le16(hdev->devid_version, ptr + 8);
945
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700946 ptr += 10;
947 }
948
Johan Hedberg213202e2013-01-27 00:31:33 +0200949 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200950 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200951 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300952}
953
Johan Hedberg890ea892013-03-15 17:06:52 -0500954static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300955{
Johan Hedberg890ea892013-03-15 17:06:52 -0500956 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300957 struct hci_cp_write_eir cp;
958
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200959 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500960 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200961
Johan Hedberg976eb202012-10-24 21:12:01 +0300962 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500963 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300964
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200965 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500966 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200968 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970
971 memset(&cp, 0, sizeof(cp));
972
973 create_eir(hdev, cp.data);
974
975 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300977
978 memcpy(hdev->eir, cp.data, sizeof(cp.data));
979
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981}
982
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200983static u8 get_service_classes(struct hci_dev *hdev)
984{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300985 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200986 u8 val = 0;
987
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300988 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200989 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200990
991 return val;
992}
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200995{
Johan Hedberg890ea892013-03-15 17:06:52 -0500996 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997 u8 cod[3];
998
999 BT_DBG("%s", hdev->name);
1000
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001001 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001002 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001003
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001004 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1005 return;
1006
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001007 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001008 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009
1010 cod[0] = hdev->minor_class;
1011 cod[1] = hdev->major_class;
1012 cod[2] = get_service_classes(hdev);
1013
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001014 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1015 cod[1] |= 0x20;
1016
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001017 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001018 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001019
Johan Hedberg890ea892013-03-15 17:06:52 -05001020 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001021}
1022
Johan Hedberga4858cb2014-02-25 19:56:31 +02001023static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001024{
1025 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001026
1027 /* If there's a pending mgmt command the flag will not yet have
1028 * it's final value, so check for this first.
1029 */
1030 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1031 if (cmd) {
1032 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001033 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001034 }
1035
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037}
1038
1039static void enable_advertising(struct hci_request *req)
1040{
1041 struct hci_dev *hdev = req->hdev;
1042 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001043 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001044 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001045
Johan Hedberg8d972502014-02-28 12:54:14 +02001046 /* Clear the HCI_ADVERTISING bit temporarily so that the
1047 * hci_update_random_address knows that it's safe to go ahead
1048 * and write a new random address. The flag will be set back on
1049 * as soon as the SET_ADV_ENABLE HCI command completes.
1050 */
1051 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
1052
Johan Hedberga4858cb2014-02-25 19:56:31 +02001053 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001054
Johan Hedberga4858cb2014-02-25 19:56:31 +02001055 /* Set require_privacy to true only when non-connectable
1056 * advertising is used. In that case it is fine to use a
1057 * non-resolvable private address.
1058 */
1059 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001060 return;
1061
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001062 memset(&cp, 0, sizeof(cp));
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001063 cp.min_interval = cpu_to_le16(0x0800);
1064 cp.max_interval = cpu_to_le16(0x0800);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001066 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001067 cp.channel_map = hdev->le_adv_channel_map;
1068
1069 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1070
1071 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1072}
1073
1074static void disable_advertising(struct hci_request *req)
1075{
1076 u8 enable = 0x00;
1077
1078 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1079}
1080
Johan Hedberg7d785252011-12-15 00:47:39 +02001081static void service_cache_off(struct work_struct *work)
1082{
1083 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001084 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001085 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001086
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001087 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001088 return;
1089
Johan Hedberg890ea892013-03-15 17:06:52 -05001090 hci_req_init(&req, hdev);
1091
Johan Hedberg7d785252011-12-15 00:47:39 +02001092 hci_dev_lock(hdev);
1093
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 update_eir(&req);
1095 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001096
1097 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001098
1099 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001100}
1101
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001102static void rpa_expired(struct work_struct *work)
1103{
1104 struct hci_dev *hdev = container_of(work, struct hci_dev,
1105 rpa_expired.work);
1106 struct hci_request req;
1107
1108 BT_DBG("");
1109
1110 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1111
1112 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) ||
1113 hci_conn_num(hdev, LE_LINK) > 0)
1114 return;
1115
1116 /* The generation of a new RPA and programming it into the
1117 * controller happens in the enable_advertising() function.
1118 */
1119
1120 hci_req_init(&req, hdev);
1121
1122 disable_advertising(&req);
1123 enable_advertising(&req);
1124
1125 hci_req_run(&req, NULL);
1126}
1127
Johan Hedberg6a919082012-02-28 06:17:26 +02001128static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001129{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001130 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001131 return;
1132
Johan Hedberg4f87da82012-03-02 19:55:56 +02001133 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001134 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001135
Johan Hedberg4f87da82012-03-02 19:55:56 +02001136 /* Non-mgmt controlled devices get this bit set
1137 * implicitly so that pairing works for them, however
1138 * for mgmt we require user-space to explicitly enable
1139 * it
1140 */
1141 clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001142}
1143
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001144static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001145 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001146{
1147 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001148
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001149 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001150
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001151 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001152
Johan Hedberg03811012010-12-08 00:21:06 +02001153 memset(&rp, 0, sizeof(rp));
1154
Johan Hedberg03811012010-12-08 00:21:06 +02001155 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001156
1157 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001158 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001159
1160 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1161 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1162
1163 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001164
1165 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001166 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001168 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001169
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001170 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001171 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001172}
1173
1174static void mgmt_pending_free(struct pending_cmd *cmd)
1175{
1176 sock_put(cmd->sk);
1177 kfree(cmd->param);
1178 kfree(cmd);
1179}
1180
1181static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001182 struct hci_dev *hdev, void *data,
1183 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001184{
1185 struct pending_cmd *cmd;
1186
Johan Hedbergfca20012014-06-28 17:54:05 +03001187 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001188 if (!cmd)
1189 return NULL;
1190
1191 cmd->opcode = opcode;
1192 cmd->index = hdev->id;
1193
Andre Guedes12b94562012-06-07 19:05:45 -03001194 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001195 if (!cmd->param) {
1196 kfree(cmd);
1197 return NULL;
1198 }
1199
1200 if (data)
1201 memcpy(cmd->param, data, len);
1202
1203 cmd->sk = sk;
1204 sock_hold(sk);
1205
1206 list_add(&cmd->list, &hdev->mgmt_pending);
1207
1208 return cmd;
1209}
1210
1211static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001212 void (*cb)(struct pending_cmd *cmd,
1213 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001214 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001215{
Andre Guedesa3d09352013-02-01 11:21:30 -03001216 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001217
Andre Guedesa3d09352013-02-01 11:21:30 -03001218 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001219 if (opcode > 0 && cmd->opcode != opcode)
1220 continue;
1221
1222 cb(cmd, data);
1223 }
1224}
1225
Johan Hedberg03811012010-12-08 00:21:06 +02001226static void mgmt_pending_remove(struct pending_cmd *cmd)
1227{
1228 list_del(&cmd->list);
1229 mgmt_pending_free(cmd);
1230}
1231
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001232static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001233{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001234 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001235
Johan Hedbergaee9b212012-02-18 15:07:59 +02001236 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001237 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001238}
1239
Johan Hedberg8b064a32014-02-24 14:52:22 +02001240static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1241{
1242 BT_DBG("%s status 0x%02x", hdev->name, status);
1243
Johan Hedberga3172b72014-02-28 09:33:44 +02001244 if (hci_conn_count(hdev) == 0) {
1245 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001246 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001247 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001248}
1249
Johan Hedberg21a60d32014-06-10 14:05:58 +03001250static void hci_stop_discovery(struct hci_request *req)
1251{
1252 struct hci_dev *hdev = req->hdev;
1253 struct hci_cp_remote_name_req_cancel cp;
1254 struct inquiry_entry *e;
1255
1256 switch (hdev->discovery.state) {
1257 case DISCOVERY_FINDING:
1258 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1259 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1260 } else {
1261 cancel_delayed_work(&hdev->le_scan_disable);
1262 hci_req_add_le_scan_disable(req);
1263 }
1264
1265 break;
1266
1267 case DISCOVERY_RESOLVING:
1268 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1269 NAME_PENDING);
1270 if (!e)
1271 return;
1272
1273 bacpy(&cp.bdaddr, &e->data.bdaddr);
1274 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1275 &cp);
1276
1277 break;
1278
1279 default:
1280 /* Passive scanning */
1281 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
1282 hci_req_add_le_scan_disable(req);
1283 break;
1284 }
1285}
1286
Johan Hedberg8b064a32014-02-24 14:52:22 +02001287static int clean_up_hci_state(struct hci_dev *hdev)
1288{
1289 struct hci_request req;
1290 struct hci_conn *conn;
1291
1292 hci_req_init(&req, hdev);
1293
1294 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1295 test_bit(HCI_PSCAN, &hdev->flags)) {
1296 u8 scan = 0x00;
1297 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1298 }
1299
1300 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
1301 disable_advertising(&req);
1302
Johan Hedbergf8680f12014-06-10 14:05:59 +03001303 hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001304
1305 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1306 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001307 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001308
Johan Hedbergc9910d02014-02-27 14:35:12 +02001309 switch (conn->state) {
1310 case BT_CONNECTED:
1311 case BT_CONFIG:
1312 dc.handle = cpu_to_le16(conn->handle);
1313 dc.reason = 0x15; /* Terminated due to Power Off */
1314 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1315 break;
1316 case BT_CONNECT:
1317 if (conn->type == LE_LINK)
1318 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1319 0, NULL);
1320 else if (conn->type == ACL_LINK)
1321 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1322 6, &conn->dst);
1323 break;
1324 case BT_CONNECT2:
1325 bacpy(&rej.bdaddr, &conn->dst);
1326 rej.reason = 0x15; /* Terminated due to Power Off */
1327 if (conn->type == ACL_LINK)
1328 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1329 sizeof(rej), &rej);
1330 else if (conn->type == SCO_LINK)
1331 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1332 sizeof(rej), &rej);
1333 break;
1334 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001335 }
1336
1337 return hci_req_run(&req, clean_up_hci_complete);
1338}
1339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001340static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001341 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001342{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001343 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001344 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001345 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001346
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001347 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001348
Johan Hedberga7e80f22013-01-09 16:05:19 +02001349 if (cp->val != 0x00 && cp->val != 0x01)
1350 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1351 MGMT_STATUS_INVALID_PARAMS);
1352
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001353 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001354
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001355 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1356 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1357 MGMT_STATUS_BUSY);
1358 goto failed;
1359 }
1360
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001361 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1362 cancel_delayed_work(&hdev->power_off);
1363
1364 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001365 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1366 data, len);
1367 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001368 goto failed;
1369 }
1370 }
1371
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001372 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001373 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001374 goto failed;
1375 }
1376
Johan Hedberg03811012010-12-08 00:21:06 +02001377 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1378 if (!cmd) {
1379 err = -ENOMEM;
1380 goto failed;
1381 }
1382
Johan Hedberg8b064a32014-02-24 14:52:22 +02001383 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001384 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001385 err = 0;
1386 } else {
1387 /* Disconnect connections, stop scans, etc */
1388 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001389 if (!err)
1390 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1391 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001392
Johan Hedberg8b064a32014-02-24 14:52:22 +02001393 /* ENODATA means there were no HCI commands queued */
1394 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001395 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001396 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1397 err = 0;
1398 }
1399 }
Johan Hedberg03811012010-12-08 00:21:06 +02001400
1401failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001402 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001403 return err;
1404}
1405
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001406static int new_settings(struct hci_dev *hdev, struct sock *skip)
1407{
1408 __le32 ev;
1409
1410 ev = cpu_to_le32(get_current_settings(hdev));
1411
1412 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1413}
1414
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001415struct cmd_lookup {
1416 struct sock *sk;
1417 struct hci_dev *hdev;
1418 u8 mgmt_status;
1419};
1420
1421static void settings_rsp(struct pending_cmd *cmd, void *data)
1422{
1423 struct cmd_lookup *match = data;
1424
1425 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1426
1427 list_del(&cmd->list);
1428
1429 if (match->sk == NULL) {
1430 match->sk = cmd->sk;
1431 sock_hold(match->sk);
1432 }
1433
1434 mgmt_pending_free(cmd);
1435}
1436
1437static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1438{
1439 u8 *status = data;
1440
1441 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1442 mgmt_pending_remove(cmd);
1443}
1444
Johan Hedberge6fe7982013-10-02 15:45:22 +03001445static u8 mgmt_bredr_support(struct hci_dev *hdev)
1446{
1447 if (!lmp_bredr_capable(hdev))
1448 return MGMT_STATUS_NOT_SUPPORTED;
1449 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1450 return MGMT_STATUS_REJECTED;
1451 else
1452 return MGMT_STATUS_SUCCESS;
1453}
1454
1455static u8 mgmt_le_support(struct hci_dev *hdev)
1456{
1457 if (!lmp_le_capable(hdev))
1458 return MGMT_STATUS_NOT_SUPPORTED;
1459 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1460 return MGMT_STATUS_REJECTED;
1461 else
1462 return MGMT_STATUS_SUCCESS;
1463}
1464
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001465static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1466{
1467 struct pending_cmd *cmd;
1468 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001469 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001470 bool changed;
1471
1472 BT_DBG("status 0x%02x", status);
1473
1474 hci_dev_lock(hdev);
1475
1476 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1477 if (!cmd)
1478 goto unlock;
1479
1480 if (status) {
1481 u8 mgmt_err = mgmt_status(status);
1482 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001483 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001484 goto remove_cmd;
1485 }
1486
1487 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001488 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001489 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1490 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001491
1492 if (hdev->discov_timeout > 0) {
1493 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1494 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1495 to);
1496 }
1497 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001498 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1499 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001500 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001501
1502 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1503
1504 if (changed)
1505 new_settings(hdev, cmd->sk);
1506
Marcel Holtmann970ba522013-10-15 06:33:57 -07001507 /* When the discoverable mode gets changed, make sure
1508 * that class of device has the limited discoverable
1509 * bit correctly set.
1510 */
1511 hci_req_init(&req, hdev);
1512 update_class(&req);
1513 hci_req_run(&req, NULL);
1514
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001515remove_cmd:
1516 mgmt_pending_remove(cmd);
1517
1518unlock:
1519 hci_dev_unlock(hdev);
1520}
1521
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001522static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001523 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001524{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001525 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001526 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001527 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001528 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001529 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001530 int err;
1531
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001532 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001533
Johan Hedberg9a43e252013-10-20 19:00:07 +03001534 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1535 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001536 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001537 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001538
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001540 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1541 MGMT_STATUS_INVALID_PARAMS);
1542
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001543 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001544
1545 /* Disabling discoverable requires that no timeout is set,
1546 * and enabling limited discoverable requires a timeout.
1547 */
1548 if ((cp->val == 0x00 && timeout > 0) ||
1549 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001550 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001551 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001552
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001553 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001554
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001555 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001556 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001557 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001558 goto failed;
1559 }
1560
1561 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001562 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001563 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001564 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001565 goto failed;
1566 }
1567
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001568 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001569 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001570 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001571 goto failed;
1572 }
1573
1574 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001575 bool changed = false;
1576
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001577 /* Setting limited discoverable when powered off is
1578 * not a valid operation since it requires a timeout
1579 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1580 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001581 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1582 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1583 changed = true;
1584 }
1585
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001587 if (err < 0)
1588 goto failed;
1589
1590 if (changed)
1591 err = new_settings(hdev, sk);
1592
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001593 goto failed;
1594 }
1595
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001596 /* If the current mode is the same, then just update the timeout
1597 * value with the new value. And if only the timeout gets updated,
1598 * then no need for any HCI transactions.
1599 */
1600 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1601 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1602 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001603 cancel_delayed_work(&hdev->discov_off);
1604 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001605
Marcel Holtmann36261542013-10-15 08:28:51 -07001606 if (cp->val && hdev->discov_timeout > 0) {
1607 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001608 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001609 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001610 }
1611
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001612 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001613 goto failed;
1614 }
1615
1616 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1617 if (!cmd) {
1618 err = -ENOMEM;
1619 goto failed;
1620 }
1621
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001622 /* Cancel any potential discoverable timeout that might be
1623 * still active and store new timeout value. The arming of
1624 * the timeout happens in the complete handler.
1625 */
1626 cancel_delayed_work(&hdev->discov_off);
1627 hdev->discov_timeout = timeout;
1628
Johan Hedbergb456f872013-10-19 23:38:22 +03001629 /* Limited discoverable mode */
1630 if (cp->val == 0x02)
1631 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1632 else
1633 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1634
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001635 hci_req_init(&req, hdev);
1636
Johan Hedberg9a43e252013-10-20 19:00:07 +03001637 /* The procedure for LE-only controllers is much simpler - just
1638 * update the advertising data.
1639 */
1640 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1641 goto update_ad;
1642
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001643 scan = SCAN_PAGE;
1644
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001645 if (cp->val) {
1646 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001647
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001648 if (cp->val == 0x02) {
1649 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001650 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001651 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1652 hci_cp.iac_lap[1] = 0x8b;
1653 hci_cp.iac_lap[2] = 0x9e;
1654 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1655 hci_cp.iac_lap[4] = 0x8b;
1656 hci_cp.iac_lap[5] = 0x9e;
1657 } else {
1658 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001659 hci_cp.num_iac = 1;
1660 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1661 hci_cp.iac_lap[1] = 0x8b;
1662 hci_cp.iac_lap[2] = 0x9e;
1663 }
1664
1665 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1666 (hci_cp.num_iac * 3) + 1, &hci_cp);
1667
1668 scan |= SCAN_INQUIRY;
1669 } else {
1670 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1671 }
1672
1673 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001674
Johan Hedberg9a43e252013-10-20 19:00:07 +03001675update_ad:
1676 update_adv_data(&req);
1677
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001678 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001679 if (err < 0)
1680 mgmt_pending_remove(cmd);
1681
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001682failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001683 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001684 return err;
1685}
1686
Johan Hedberg406d7802013-03-15 17:07:09 -05001687static void write_fast_connectable(struct hci_request *req, bool enable)
1688{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001689 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001690 struct hci_cp_write_page_scan_activity acp;
1691 u8 type;
1692
Johan Hedberg547003b2013-10-21 16:51:53 +03001693 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1694 return;
1695
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001696 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1697 return;
1698
Johan Hedberg406d7802013-03-15 17:07:09 -05001699 if (enable) {
1700 type = PAGE_SCAN_TYPE_INTERLACED;
1701
1702 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001703 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001704 } else {
1705 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1706
1707 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001708 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001709 }
1710
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001711 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001712
Johan Hedbergbd98b992013-03-15 17:07:13 -05001713 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1714 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1715 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1716 sizeof(acp), &acp);
1717
1718 if (hdev->page_scan_type != type)
1719 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001720}
1721
Johan Hedberg2b76f452013-03-15 17:07:04 -05001722static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1723{
1724 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001725 struct mgmt_mode *cp;
1726 bool changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001727
1728 BT_DBG("status 0x%02x", status);
1729
1730 hci_dev_lock(hdev);
1731
1732 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1733 if (!cmd)
1734 goto unlock;
1735
Johan Hedberg37438c12013-10-14 16:20:05 +03001736 if (status) {
1737 u8 mgmt_err = mgmt_status(status);
1738 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1739 goto remove_cmd;
1740 }
1741
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001742 cp = cmd->param;
1743 if (cp->val)
1744 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1745 else
1746 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1747
Johan Hedberg2b76f452013-03-15 17:07:04 -05001748 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1749
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001750 if (changed)
1751 new_settings(hdev, cmd->sk);
1752
Johan Hedberg37438c12013-10-14 16:20:05 +03001753remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001754 mgmt_pending_remove(cmd);
1755
1756unlock:
1757 hci_dev_unlock(hdev);
1758}
1759
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001760static int set_connectable_update_settings(struct hci_dev *hdev,
1761 struct sock *sk, u8 val)
1762{
1763 bool changed = false;
1764 int err;
1765
1766 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1767 changed = true;
1768
1769 if (val) {
1770 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1771 } else {
1772 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1773 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1774 }
1775
1776 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1777 if (err < 0)
1778 return err;
1779
1780 if (changed)
1781 return new_settings(hdev, sk);
1782
1783 return 0;
1784}
1785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001786static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001787 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001788{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001789 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001790 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001791 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001792 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001793 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001794
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001795 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001796
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001797 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1798 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001799 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001800 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001801
Johan Hedberga7e80f22013-01-09 16:05:19 +02001802 if (cp->val != 0x00 && cp->val != 0x01)
1803 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1804 MGMT_STATUS_INVALID_PARAMS);
1805
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001806 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001807
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001808 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001809 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001810 goto failed;
1811 }
1812
1813 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001814 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001815 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001816 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001817 goto failed;
1818 }
1819
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001820 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1821 if (!cmd) {
1822 err = -ENOMEM;
1823 goto failed;
1824 }
1825
Johan Hedberg2b76f452013-03-15 17:07:04 -05001826 hci_req_init(&req, hdev);
1827
Johan Hedberg9a43e252013-10-20 19:00:07 +03001828 /* If BR/EDR is not enabled and we disable advertising as a
1829 * by-product of disabling connectable, we need to update the
1830 * advertising flags.
1831 */
1832 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1833 if (!cp->val) {
1834 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1835 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1836 }
1837 update_adv_data(&req);
1838 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001839 if (cp->val) {
1840 scan = SCAN_PAGE;
1841 } else {
1842 scan = 0;
1843
1844 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001845 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001846 cancel_delayed_work(&hdev->discov_off);
1847 }
1848
1849 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1850 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001851
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001852 /* If we're going from non-connectable to connectable or
1853 * vice-versa when fast connectable is enabled ensure that fast
1854 * connectable gets disabled. write_fast_connectable won't do
1855 * anything if the page scan parameters are already what they
1856 * should be.
1857 */
1858 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001859 write_fast_connectable(&req, false);
1860
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001861 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) &&
1862 hci_conn_num(hdev, LE_LINK) == 0) {
1863 disable_advertising(&req);
1864 enable_advertising(&req);
1865 }
1866
Johan Hedberg2b76f452013-03-15 17:07:04 -05001867 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001868 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001869 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001870 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001871 err = set_connectable_update_settings(hdev, sk,
1872 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001873 goto failed;
1874 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001875
1876failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001877 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001878 return err;
1879}
1880
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001881static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001882 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001883{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001884 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001885 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001886 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001887
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001888 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889
Johan Hedberga7e80f22013-01-09 16:05:19 +02001890 if (cp->val != 0x00 && cp->val != 0x01)
1891 return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE,
1892 MGMT_STATUS_INVALID_PARAMS);
1893
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001894 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001895
1896 if (cp->val)
Marcel Holtmann55594352013-10-06 16:11:57 -07001897 changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001898 else
Marcel Holtmann55594352013-10-06 16:11:57 -07001899 changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001900
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001901 err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001902 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001903 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001904
Marcel Holtmann55594352013-10-06 16:11:57 -07001905 if (changed)
1906 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001907
Marcel Holtmann55594352013-10-06 16:11:57 -07001908unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001909 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001910 return err;
1911}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001912
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001913static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1914 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001915{
1916 struct mgmt_mode *cp = data;
1917 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001918 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001919 int err;
1920
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001921 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001922
Johan Hedberge6fe7982013-10-02 15:45:22 +03001923 status = mgmt_bredr_support(hdev);
1924 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001925 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001926 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001927
Johan Hedberga7e80f22013-01-09 16:05:19 +02001928 if (cp->val != 0x00 && cp->val != 0x01)
1929 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
1930 MGMT_STATUS_INVALID_PARAMS);
1931
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001932 hci_dev_lock(hdev);
1933
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001934 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001935 bool changed = false;
1936
1937 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001938 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02001939 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
1940 changed = true;
1941 }
1942
1943 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1944 if (err < 0)
1945 goto failed;
1946
1947 if (changed)
1948 err = new_settings(hdev, sk);
1949
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001950 goto failed;
1951 }
1952
1953 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001954 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001955 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001956 goto failed;
1957 }
1958
1959 val = !!cp->val;
1960
1961 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
1962 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
1963 goto failed;
1964 }
1965
1966 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
1967 if (!cmd) {
1968 err = -ENOMEM;
1969 goto failed;
1970 }
1971
1972 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
1973 if (err < 0) {
1974 mgmt_pending_remove(cmd);
1975 goto failed;
1976 }
1977
1978failed:
1979 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001980 return err;
1981}
1982
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001983static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001984{
1985 struct mgmt_mode *cp = data;
1986 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07001987 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001988 int err;
1989
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001990 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001991
Marcel Holtmanncdba5282013-10-02 21:31:52 -07001992 status = mgmt_bredr_support(hdev);
1993 if (status)
1994 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
1995
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02001996 if (!lmp_ssp_capable(hdev))
1997 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
1998 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02001999
Johan Hedberga7e80f22013-01-09 16:05:19 +02002000 if (cp->val != 0x00 && cp->val != 0x01)
2001 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2002 MGMT_STATUS_INVALID_PARAMS);
2003
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002004 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002005
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002006 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002007 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002008
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002009 if (cp->val) {
2010 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2011 &hdev->dev_flags);
2012 } else {
2013 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2014 &hdev->dev_flags);
2015 if (!changed)
2016 changed = test_and_clear_bit(HCI_HS_ENABLED,
2017 &hdev->dev_flags);
2018 else
2019 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002020 }
2021
2022 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2023 if (err < 0)
2024 goto failed;
2025
2026 if (changed)
2027 err = new_settings(hdev, sk);
2028
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002029 goto failed;
2030 }
2031
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002032 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2033 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002034 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2035 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002036 goto failed;
2037 }
2038
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002039 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002040 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2041 goto failed;
2042 }
2043
2044 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2045 if (!cmd) {
2046 err = -ENOMEM;
2047 goto failed;
2048 }
2049
Johan Hedberg37699722014-06-24 14:00:27 +03002050 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2051 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2052 sizeof(cp->val), &cp->val);
2053
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002054 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002066{
2067 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002068 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002069 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002070 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002073
Johan Hedberge6fe7982013-10-02 15:45:22 +03002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002077
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2080 MGMT_STATUS_NOT_SUPPORTED);
2081
2082 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2084 MGMT_STATUS_REJECTED);
2085
Johan Hedberga7e80f22013-01-09 16:05:19 +02002086 if (cp->val != 0x00 && cp->val != 0x01)
2087 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2088 MGMT_STATUS_INVALID_PARAMS);
2089
Marcel Holtmannee392692013-10-01 22:59:23 -07002090 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002091
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002092 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002093 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002094 } else {
2095 if (hdev_is_powered(hdev)) {
2096 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2097 MGMT_STATUS_REJECTED);
2098 goto unlock;
2099 }
2100
Marcel Holtmannee392692013-10-01 22:59:23 -07002101 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002102 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2105 if (err < 0)
2106 goto unlock;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
2111unlock:
2112 hci_dev_unlock(hdev);
2113 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002114}
2115
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002116static void le_enable_complete(struct hci_dev *hdev, u8 status)
2117{
2118 struct cmd_lookup match = { NULL, hdev };
2119
2120 if (status) {
2121 u8 mgmt_err = mgmt_status(status);
2122
2123 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2124 &mgmt_err);
2125 return;
2126 }
2127
2128 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2129
2130 new_settings(hdev, match.sk);
2131
2132 if (match.sk)
2133 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002134
2135 /* Make sure the controller has a good default for
2136 * advertising data. Restrict the update to when LE
2137 * has actually been enabled. During power on, the
2138 * update in powered_update_hci will take care of it.
2139 */
2140 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2141 struct hci_request req;
2142
2143 hci_dev_lock(hdev);
2144
2145 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002146 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002147 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002148 hci_req_run(&req, NULL);
2149
2150 hci_dev_unlock(hdev);
2151 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002152}
2153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002155{
2156 struct mgmt_mode *cp = data;
2157 struct hci_cp_write_le_host_supported hci_cp;
2158 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002159 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002160 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002161 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002162
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002163 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002164
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002165 if (!lmp_le_capable(hdev))
2166 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2167 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002168
Johan Hedberga7e80f22013-01-09 16:05:19 +02002169 if (cp->val != 0x00 && cp->val != 0x01)
2170 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2171 MGMT_STATUS_INVALID_PARAMS);
2172
Johan Hedbergc73eee92013-04-19 18:35:21 +03002173 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002174 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002175 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2176 MGMT_STATUS_REJECTED);
2177
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002178 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002179
2180 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002181 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002182
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002183 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002184 bool changed = false;
2185
2186 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2187 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2188 changed = true;
2189 }
2190
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002191 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2192 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002193 changed = true;
2194 }
2195
Johan Hedberg06199cf2012-02-22 16:37:11 +02002196 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2197 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002198 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002199
2200 if (changed)
2201 err = new_settings(hdev, sk);
2202
Johan Hedberg1de028c2012-02-29 19:55:35 -08002203 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002204 }
2205
Johan Hedberg4375f102013-09-25 13:26:10 +03002206 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2207 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002208 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002209 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002210 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002211 }
2212
2213 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2214 if (!cmd) {
2215 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002216 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002217 }
2218
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002219 hci_req_init(&req, hdev);
2220
Johan Hedberg06199cf2012-02-22 16:37:11 +02002221 memset(&hci_cp, 0, sizeof(hci_cp));
2222
2223 if (val) {
2224 hci_cp.le = val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002225 hci_cp.simul = lmp_le_br_capable(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002226 } else {
2227 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
2228 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002229 }
2230
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002231 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2232 &hci_cp);
2233
2234 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302235 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002237
Johan Hedberg1de028c2012-02-29 19:55:35 -08002238unlock:
2239 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240 return err;
2241}
2242
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002243/* This is a helper function to test for pending mgmt commands that can
2244 * cause CoD or EIR HCI commands. We can only allow one such pending
2245 * mgmt command at a time since otherwise we cannot easily track what
2246 * the current values are, will be, and based on that calculate if a new
2247 * HCI command needs to be sent and if yes with what value.
2248 */
2249static bool pending_eir_or_class(struct hci_dev *hdev)
2250{
2251 struct pending_cmd *cmd;
2252
2253 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2254 switch (cmd->opcode) {
2255 case MGMT_OP_ADD_UUID:
2256 case MGMT_OP_REMOVE_UUID:
2257 case MGMT_OP_SET_DEV_CLASS:
2258 case MGMT_OP_SET_POWERED:
2259 return true;
2260 }
2261 }
2262
2263 return false;
2264}
2265
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002266static const u8 bluetooth_base_uuid[] = {
2267 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2268 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2269};
2270
2271static u8 get_uuid_size(const u8 *uuid)
2272{
2273 u32 val;
2274
2275 if (memcmp(uuid, bluetooth_base_uuid, 12))
2276 return 128;
2277
2278 val = get_unaligned_le32(&uuid[12]);
2279 if (val > 0xffff)
2280 return 32;
2281
2282 return 16;
2283}
2284
Johan Hedberg92da6092013-03-15 17:06:55 -05002285static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2286{
2287 struct pending_cmd *cmd;
2288
2289 hci_dev_lock(hdev);
2290
2291 cmd = mgmt_pending_find(mgmt_op, hdev);
2292 if (!cmd)
2293 goto unlock;
2294
2295 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2296 hdev->dev_class, 3);
2297
2298 mgmt_pending_remove(cmd);
2299
2300unlock:
2301 hci_dev_unlock(hdev);
2302}
2303
2304static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2305{
2306 BT_DBG("status 0x%02x", status);
2307
2308 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2309}
2310
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002311static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002312{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002313 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002314 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002315 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002316 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002317 int err;
2318
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002319 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002320
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002321 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002322
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002323 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002324 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002325 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002326 goto failed;
2327 }
2328
Andre Guedes92c4c202012-06-07 19:05:44 -03002329 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002330 if (!uuid) {
2331 err = -ENOMEM;
2332 goto failed;
2333 }
2334
2335 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002336 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002337 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002338
Johan Hedbergde66aa62013-01-27 00:31:27 +02002339 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002340
Johan Hedberg890ea892013-03-15 17:06:52 -05002341 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002342
Johan Hedberg890ea892013-03-15 17:06:52 -05002343 update_class(&req);
2344 update_eir(&req);
2345
Johan Hedberg92da6092013-03-15 17:06:55 -05002346 err = hci_req_run(&req, add_uuid_complete);
2347 if (err < 0) {
2348 if (err != -ENODATA)
2349 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002350
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002351 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002352 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002353 goto failed;
2354 }
2355
2356 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002357 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002358 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002359 goto failed;
2360 }
2361
2362 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002363
2364failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002365 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002366 return err;
2367}
2368
Johan Hedberg24b78d02012-02-23 23:24:30 +02002369static bool enable_service_cache(struct hci_dev *hdev)
2370{
2371 if (!hdev_is_powered(hdev))
2372 return false;
2373
2374 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002375 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2376 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002377 return true;
2378 }
2379
2380 return false;
2381}
2382
Johan Hedberg92da6092013-03-15 17:06:55 -05002383static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2384{
2385 BT_DBG("status 0x%02x", status);
2386
2387 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2388}
2389
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002390static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002391 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002392{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002393 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002394 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002395 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396 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 -05002397 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002398 int err, found;
2399
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002400 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002402 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002403
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002404 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002406 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002407 goto unlock;
2408 }
2409
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002410 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002411 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002412
Johan Hedberg24b78d02012-02-23 23:24:30 +02002413 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002414 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002415 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002416 goto unlock;
2417 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002418
Johan Hedberg9246a862012-02-23 21:33:16 +02002419 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002420 }
2421
2422 found = 0;
2423
Johan Hedberg056341c2013-01-27 00:31:30 +02002424 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2426 continue;
2427
2428 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002429 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002430 found++;
2431 }
2432
2433 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002434 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002435 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002436 goto unlock;
2437 }
2438
Johan Hedberg9246a862012-02-23 21:33:16 +02002439update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002440 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002441
Johan Hedberg890ea892013-03-15 17:06:52 -05002442 update_class(&req);
2443 update_eir(&req);
2444
Johan Hedberg92da6092013-03-15 17:06:55 -05002445 err = hci_req_run(&req, remove_uuid_complete);
2446 if (err < 0) {
2447 if (err != -ENODATA)
2448 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002449
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002450 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002451 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002452 goto unlock;
2453 }
2454
2455 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002456 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002457 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002458 goto unlock;
2459 }
2460
2461 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002462
2463unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002464 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002465 return err;
2466}
2467
Johan Hedberg92da6092013-03-15 17:06:55 -05002468static void set_class_complete(struct hci_dev *hdev, u8 status)
2469{
2470 BT_DBG("status 0x%02x", status);
2471
2472 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2473}
2474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002475static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002476 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002477{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002478 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002479 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002480 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002481 int err;
2482
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002483 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002484
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002485 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002486 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2487 MGMT_STATUS_NOT_SUPPORTED);
2488
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002489 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002490
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002491 if (pending_eir_or_class(hdev)) {
2492 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2493 MGMT_STATUS_BUSY);
2494 goto unlock;
2495 }
2496
2497 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2498 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2499 MGMT_STATUS_INVALID_PARAMS);
2500 goto unlock;
2501 }
2502
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002503 hdev->major_class = cp->major;
2504 hdev->minor_class = cp->minor;
2505
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002506 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002507 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002508 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002509 goto unlock;
2510 }
2511
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 hci_req_init(&req, hdev);
2513
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002514 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002515 hci_dev_unlock(hdev);
2516 cancel_delayed_work_sync(&hdev->service_cache);
2517 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002518 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002519 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002520
Johan Hedberg890ea892013-03-15 17:06:52 -05002521 update_class(&req);
2522
Johan Hedberg92da6092013-03-15 17:06:55 -05002523 err = hci_req_run(&req, set_class_complete);
2524 if (err < 0) {
2525 if (err != -ENODATA)
2526 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002527
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002528 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002529 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002530 goto unlock;
2531 }
2532
2533 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002534 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002535 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002536 goto unlock;
2537 }
2538
2539 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002540
Johan Hedbergb5235a62012-02-21 14:32:24 +02002541unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002542 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002543 return err;
2544}
2545
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002546static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002547 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002548{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002549 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002550 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2551 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002552 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002553 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002554 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002555
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002556 BT_DBG("request for %s", hdev->name);
2557
2558 if (!lmp_bredr_capable(hdev))
2559 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2560 MGMT_STATUS_NOT_SUPPORTED);
2561
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002562 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002563 if (key_count > max_key_count) {
2564 BT_ERR("load_link_keys: too big key_count value %u",
2565 key_count);
2566 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2567 MGMT_STATUS_INVALID_PARAMS);
2568 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002569
Johan Hedberg86742e12011-11-07 23:13:38 +02002570 expected_len = sizeof(*cp) + key_count *
2571 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002572 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002573 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002574 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002575 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002576 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002577 }
2578
Johan Hedberg4ae143012013-01-20 14:27:13 +02002579 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2580 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2581 MGMT_STATUS_INVALID_PARAMS);
2582
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002583 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002584 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002585
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002586 for (i = 0; i < key_count; i++) {
2587 struct mgmt_link_key_info *key = &cp->keys[i];
2588
Marcel Holtmann8e991132014-01-10 02:07:25 -08002589 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002590 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2591 MGMT_STATUS_INVALID_PARAMS);
2592 }
2593
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002594 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002595
2596 hci_link_keys_clear(hdev);
2597
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002598 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002599 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2600 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002601 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002602 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2603 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002604
2605 if (changed)
2606 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002607
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002608 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002609 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002610
Johan Hedberg58e92932014-06-24 14:00:26 +03002611 /* Always ignore debug keys and require a new pairing if
2612 * the user wants to use them.
2613 */
2614 if (key->type == HCI_LK_DEBUG_COMBINATION)
2615 continue;
2616
Johan Hedberg7652ff62014-06-24 13:15:49 +03002617 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2618 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002619 }
2620
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002621 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002622
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002623 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002624
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002625 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002626}
2627
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002628static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002629 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002630{
2631 struct mgmt_ev_device_unpaired ev;
2632
2633 bacpy(&ev.addr.bdaddr, bdaddr);
2634 ev.addr.type = addr_type;
2635
2636 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002637 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002638}
2639
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002640static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002641 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002642{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002643 struct mgmt_cp_unpair_device *cp = data;
2644 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002645 struct hci_cp_disconnect dc;
2646 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002647 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002648 int err;
2649
Johan Hedberga8a1d192011-11-10 15:54:38 +02002650 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002651 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2652 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002653
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002654 if (!bdaddr_type_is_valid(cp->addr.type))
2655 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2656 MGMT_STATUS_INVALID_PARAMS,
2657 &rp, sizeof(rp));
2658
Johan Hedberg118da702013-01-20 14:27:20 +02002659 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2660 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2661 MGMT_STATUS_INVALID_PARAMS,
2662 &rp, sizeof(rp));
2663
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002664 hci_dev_lock(hdev);
2665
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002666 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002668 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002669 goto unlock;
2670 }
2671
Johan Hedberge0b2b272014-02-18 17:14:31 +02002672 if (cp->addr.type == BDADDR_BREDR) {
Johan Hedberg124f6e32012-02-09 13:50:12 +02002673 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002674 } else {
2675 u8 addr_type;
2676
2677 if (cp->addr.type == BDADDR_LE_PUBLIC)
2678 addr_type = ADDR_LE_DEV_PUBLIC;
2679 else
2680 addr_type = ADDR_LE_DEV_RANDOM;
2681
Johan Hedberga7ec7332014-02-18 17:14:35 +02002682 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2683
Andre Guedesa9b0a042014-02-26 20:21:52 -03002684 hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
2685
Johan Hedberge0b2b272014-02-18 17:14:31 +02002686 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2687 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002688
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002689 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002690 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002691 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002692 goto unlock;
2693 }
2694
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002695 if (cp->disconnect) {
Andre Guedes591f47f2012-04-24 21:02:49 -03002696 if (cp->addr.type == BDADDR_BREDR)
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002697 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002698 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002699 else
2700 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002701 &cp->addr.bdaddr);
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002702 } else {
2703 conn = NULL;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002705
Johan Hedberga8a1d192011-11-10 15:54:38 +02002706 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002707 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002708 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002709 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002710 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711 }
2712
Johan Hedberg124f6e32012-02-09 13:50:12 +02002713 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002715 if (!cmd) {
2716 err = -ENOMEM;
2717 goto unlock;
2718 }
2719
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002720 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002721 dc.reason = 0x13; /* Remote User Terminated Connection */
2722 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2723 if (err < 0)
2724 mgmt_pending_remove(cmd);
2725
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002727 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728 return err;
2729}
2730
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002731static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002732 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002733{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002734 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002735 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002736 struct hci_cp_disconnect dc;
Johan Hedberg366a0332011-02-19 12:05:55 -03002737 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002738 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002739 int err;
2740
2741 BT_DBG("");
2742
Johan Hedberg06a63b12013-01-20 14:27:21 +02002743 memset(&rp, 0, sizeof(rp));
2744 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2745 rp.addr.type = cp->addr.type;
2746
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002747 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002748 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2749 MGMT_STATUS_INVALID_PARAMS,
2750 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002751
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002752 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002753
2754 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002755 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2756 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002757 goto failed;
2758 }
2759
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002760 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002761 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2762 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002763 goto failed;
2764 }
2765
Andre Guedes591f47f2012-04-24 21:02:49 -03002766 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002767 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2768 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002769 else
2770 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002771
Vishal Agarwalf9607272012-06-13 05:32:43 +05302772 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002773 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2774 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002775 goto failed;
2776 }
2777
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002778 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002779 if (!cmd) {
2780 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002781 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002782 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002783
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002784 dc.handle = cpu_to_le16(conn->handle);
Andre Guedes3701f942012-06-11 18:41:12 -03002785 dc.reason = HCI_ERROR_REMOTE_USER_TERM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002786
2787 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2788 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002789 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002790
2791failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002792 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002793 return err;
2794}
2795
Andre Guedes57c14772012-04-24 21:02:50 -03002796static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002797{
2798 switch (link_type) {
2799 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002800 switch (addr_type) {
2801 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002802 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002803
Johan Hedberg48264f02011-11-09 13:58:58 +02002804 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002805 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002806 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002807 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002808
Johan Hedberg4c659c32011-11-07 23:13:39 +02002809 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002810 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002811 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002812 }
2813}
2814
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002815static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2816 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002817{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002818 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002819 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002820 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002821 int err;
2822 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002823
2824 BT_DBG("");
2825
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002826 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002827
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002828 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002829 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002830 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002831 goto unlock;
2832 }
2833
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002834 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002835 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2836 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002837 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002838 }
2839
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002840 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002841 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002842 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002843 err = -ENOMEM;
2844 goto unlock;
2845 }
2846
Johan Hedberg2784eb42011-01-21 13:56:35 +02002847 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002848 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002849 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2850 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002851 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002852 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002853 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002854 continue;
2855 i++;
2856 }
2857
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002858 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002859
Johan Hedberg4c659c32011-11-07 23:13:39 +02002860 /* Recalculate length in case of filtered SCO connections, etc */
2861 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002862
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002863 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002864 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002865
Johan Hedberga38528f2011-01-22 06:46:43 +02002866 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002867
2868unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002869 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002870 return err;
2871}
2872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002873static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002874 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002875{
2876 struct pending_cmd *cmd;
2877 int err;
2878
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002879 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002880 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002881 if (!cmd)
2882 return -ENOMEM;
2883
Johan Hedbergd8457692012-02-17 14:24:57 +02002884 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002885 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002886 if (err < 0)
2887 mgmt_pending_remove(cmd);
2888
2889 return err;
2890}
2891
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002892static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002893 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002894{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002895 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002896 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002897 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002898 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002899 int err;
2900
2901 BT_DBG("");
2902
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002903 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002904
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002905 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002906 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002907 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002908 goto failed;
2909 }
2910
Johan Hedbergd8457692012-02-17 14:24:57 +02002911 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002912 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002913 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002914 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002915 goto failed;
2916 }
2917
2918 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02002919 struct mgmt_cp_pin_code_neg_reply ncp;
2920
2921 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002922
2923 BT_ERR("PIN code is not 16 bytes long");
2924
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002925 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002926 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002927 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002928 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002929
2930 goto failed;
2931 }
2932
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03002933 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002934 if (!cmd) {
2935 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002936 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002937 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02002938
Johan Hedbergd8457692012-02-17 14:24:57 +02002939 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002940 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02002941 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02002942
2943 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
2944 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002945 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002946
2947failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002948 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002949 return err;
2950}
2951
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002952static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
2953 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002954{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002955 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002956
2957 BT_DBG("");
2958
Johan Hedberg4ec86d42014-06-17 15:14:48 +03002959 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
2960 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
2961 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
2962
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002963 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002964
2965 hdev->io_capability = cp->io_capability;
2966
2967 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002968 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002970 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002971
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002972 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
2973 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02002974}
2975
Gustavo Padovan6039aa72012-05-23 04:04:18 -03002976static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03002977{
2978 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002979 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03002980
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002981 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03002982 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
2983 continue;
2984
Johan Hedberge9a416b2011-02-19 12:05:56 -03002985 if (cmd->user_data != conn)
2986 continue;
2987
2988 return cmd;
2989 }
2990
2991 return NULL;
2992}
2993
2994static void pairing_complete(struct pending_cmd *cmd, u8 status)
2995{
2996 struct mgmt_rp_pair_device rp;
2997 struct hci_conn *conn = cmd->user_data;
2998
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02002999 bacpy(&rp.addr.bdaddr, &conn->dst);
3000 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003001
Johan Hedbergaee9b212012-02-18 15:07:59 +02003002 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003004
3005 /* So we don't get further callbacks for this connection */
3006 conn->connect_cfm_cb = NULL;
3007 conn->security_cfm_cb = NULL;
3008 conn->disconn_cfm_cb = NULL;
3009
David Herrmann76a68ba2013-04-06 20:28:37 +02003010 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003011
Johan Hedberga664b5b2011-02-19 12:06:02 -03003012 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003013}
3014
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003015void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3016{
3017 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3018 struct pending_cmd *cmd;
3019
3020 cmd = find_pairing(conn);
3021 if (cmd)
3022 pairing_complete(cmd, status);
3023}
3024
Johan Hedberge9a416b2011-02-19 12:05:56 -03003025static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3026{
3027 struct pending_cmd *cmd;
3028
3029 BT_DBG("status %u", status);
3030
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003031 cmd = find_pairing(conn);
3032 if (!cmd)
3033 BT_DBG("Unable to find a pending command");
3034 else
Johan Hedberge2113262012-02-18 15:20:03 +02003035 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003036}
3037
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003038static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303039{
3040 struct pending_cmd *cmd;
3041
3042 BT_DBG("status %u", status);
3043
3044 if (!status)
3045 return;
3046
3047 cmd = find_pairing(conn);
3048 if (!cmd)
3049 BT_DBG("Unable to find a pending command");
3050 else
3051 pairing_complete(cmd, mgmt_status(status));
3052}
3053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003054static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003055 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003056{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003057 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003058 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003059 struct pending_cmd *cmd;
3060 u8 sec_level, auth_type;
3061 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003062 int err;
3063
3064 BT_DBG("");
3065
Szymon Jancf950a30e2013-01-18 12:48:07 +01003066 memset(&rp, 0, sizeof(rp));
3067 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3068 rp.addr.type = cp->addr.type;
3069
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003070 if (!bdaddr_type_is_valid(cp->addr.type))
3071 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3072 MGMT_STATUS_INVALID_PARAMS,
3073 &rp, sizeof(rp));
3074
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003075 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3076 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3077 MGMT_STATUS_INVALID_PARAMS,
3078 &rp, sizeof(rp));
3079
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003080 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003082 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003083 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3084 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003085 goto unlock;
3086 }
3087
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003088 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003089 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003091 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003092 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3093 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003094 } else {
3095 u8 addr_type;
3096
3097 /* Convert from L2CAP channel address type to HCI address type
3098 */
3099 if (cp->addr.type == BDADDR_LE_PUBLIC)
3100 addr_type = ADDR_LE_DEV_PUBLIC;
3101 else
3102 addr_type = ADDR_LE_DEV_RANDOM;
3103
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003104 /* When pairing a new device, it is expected to remember
3105 * this device for future connections. Adding the connection
3106 * parameter information ahead of time allows tracking
3107 * of the slave preferred values and will speed up any
3108 * further connection establishment.
3109 *
3110 * If connection parameters already exist, then they
3111 * will be kept and this function does nothing.
3112 */
3113 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3114
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003115 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Andre Guedes04a6c582014-02-26 20:21:44 -03003116 sec_level, auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003117 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003118
Ville Tervo30e76272011-02-22 16:10:53 -03003119 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003120 int status;
3121
3122 if (PTR_ERR(conn) == -EBUSY)
3123 status = MGMT_STATUS_BUSY;
3124 else
3125 status = MGMT_STATUS_CONNECT_FAILED;
3126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003127 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003128 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003129 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003130 goto unlock;
3131 }
3132
3133 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003134 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003135 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003136 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137 goto unlock;
3138 }
3139
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003140 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003141 if (!cmd) {
3142 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003143 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003144 goto unlock;
3145 }
3146
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003147 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003148 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003149 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003150 conn->security_cfm_cb = pairing_complete_cb;
3151 conn->disconn_cfm_cb = pairing_complete_cb;
3152 } else {
3153 conn->connect_cfm_cb = le_pairing_complete_cb;
3154 conn->security_cfm_cb = le_pairing_complete_cb;
3155 conn->disconn_cfm_cb = le_pairing_complete_cb;
3156 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003157
Johan Hedberge9a416b2011-02-19 12:05:56 -03003158 conn->io_capability = cp->io_cap;
3159 cmd->user_data = conn;
3160
3161 if (conn->state == BT_CONNECTED &&
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003162 hci_conn_security(conn, sec_level, auth_type))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003163 pairing_complete(cmd, 0);
3164
3165 err = 0;
3166
3167unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003168 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169 return err;
3170}
3171
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003172static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3173 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003174{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003175 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003176 struct pending_cmd *cmd;
3177 struct hci_conn *conn;
3178 int err;
3179
3180 BT_DBG("");
3181
Johan Hedberg28424702012-02-02 04:02:29 +02003182 hci_dev_lock(hdev);
3183
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003184 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003185 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003186 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003187 goto unlock;
3188 }
3189
Johan Hedberg28424702012-02-02 04:02:29 +02003190 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3191 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003192 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003193 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003194 goto unlock;
3195 }
3196
3197 conn = cmd->user_data;
3198
3199 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003200 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003201 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003202 goto unlock;
3203 }
3204
3205 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003207 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003208 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003209unlock:
3210 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003211 return err;
3212}
3213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003214static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003215 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003216 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003217{
Johan Hedberga5c29682011-02-19 12:05:57 -03003218 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003219 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003220 int err;
3221
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003222 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003223
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003224 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003225 err = cmd_complete(sk, hdev->id, mgmt_op,
3226 MGMT_STATUS_NOT_POWERED, addr,
3227 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003228 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003229 }
3230
Johan Hedberg1707c602013-03-15 17:07:15 -05003231 if (addr->type == BDADDR_BREDR)
3232 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003233 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003234 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003235
Johan Hedberg272d90d2012-02-09 15:26:12 +02003236 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003237 err = cmd_complete(sk, hdev->id, mgmt_op,
3238 MGMT_STATUS_NOT_CONNECTED, addr,
3239 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003240 goto done;
3241 }
3242
Johan Hedberg1707c602013-03-15 17:07:15 -05003243 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003244 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003245 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003246 err = cmd_complete(sk, hdev->id, mgmt_op,
3247 MGMT_STATUS_SUCCESS, addr,
3248 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003249 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003250 err = cmd_complete(sk, hdev->id, mgmt_op,
3251 MGMT_STATUS_FAILED, addr,
3252 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003253
Brian Gix47c15e22011-11-16 13:53:14 -08003254 goto done;
3255 }
3256
Johan Hedberg1707c602013-03-15 17:07:15 -05003257 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003258 if (!cmd) {
3259 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003260 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003261 }
3262
Brian Gix0df4c182011-11-16 13:53:13 -08003263 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003264 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3265 struct hci_cp_user_passkey_reply cp;
3266
Johan Hedberg1707c602013-03-15 17:07:15 -05003267 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003268 cp.passkey = passkey;
3269 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3270 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003271 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3272 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003273
Johan Hedberga664b5b2011-02-19 12:06:02 -03003274 if (err < 0)
3275 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003276
Brian Gix0df4c182011-11-16 13:53:13 -08003277done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003278 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003279 return err;
3280}
3281
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303282static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3283 void *data, u16 len)
3284{
3285 struct mgmt_cp_pin_code_neg_reply *cp = data;
3286
3287 BT_DBG("");
3288
Johan Hedberg1707c602013-03-15 17:07:15 -05003289 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303290 MGMT_OP_PIN_CODE_NEG_REPLY,
3291 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3292}
3293
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003294static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3295 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003296{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003297 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003298
3299 BT_DBG("");
3300
3301 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003302 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003303 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003304
Johan Hedberg1707c602013-03-15 17:07:15 -05003305 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 MGMT_OP_USER_CONFIRM_REPLY,
3307 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003308}
3309
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003312{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003313 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003314
3315 BT_DBG("");
3316
Johan Hedberg1707c602013-03-15 17:07:15 -05003317 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3319 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003320}
3321
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003322static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3323 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003324{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003325 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003326
3327 BT_DBG("");
3328
Johan Hedberg1707c602013-03-15 17:07:15 -05003329 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003330 MGMT_OP_USER_PASSKEY_REPLY,
3331 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003332}
3333
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003334static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003335 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003336{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003337 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003338
3339 BT_DBG("");
3340
Johan Hedberg1707c602013-03-15 17:07:15 -05003341 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003342 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3343 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003344}
3345
Johan Hedberg13928972013-03-15 17:07:00 -05003346static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003347{
Johan Hedberg13928972013-03-15 17:07:00 -05003348 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003349 struct hci_cp_write_local_name cp;
3350
Johan Hedberg13928972013-03-15 17:07:00 -05003351 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003352
Johan Hedberg890ea892013-03-15 17:06:52 -05003353 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003354}
3355
Johan Hedberg13928972013-03-15 17:07:00 -05003356static void set_name_complete(struct hci_dev *hdev, u8 status)
3357{
3358 struct mgmt_cp_set_local_name *cp;
3359 struct pending_cmd *cmd;
3360
3361 BT_DBG("status 0x%02x", status);
3362
3363 hci_dev_lock(hdev);
3364
3365 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3366 if (!cmd)
3367 goto unlock;
3368
3369 cp = cmd->param;
3370
3371 if (status)
3372 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3373 mgmt_status(status));
3374 else
3375 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3376 cp, sizeof(*cp));
3377
3378 mgmt_pending_remove(cmd);
3379
3380unlock:
3381 hci_dev_unlock(hdev);
3382}
3383
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003384static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003385 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003386{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003387 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003388 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003389 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003390 int err;
3391
3392 BT_DBG("");
3393
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003394 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003395
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003396 /* If the old values are the same as the new ones just return a
3397 * direct command complete event.
3398 */
3399 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3400 !memcmp(hdev->short_name, cp->short_name,
3401 sizeof(hdev->short_name))) {
3402 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3403 data, len);
3404 goto failed;
3405 }
3406
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003407 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003408
Johan Hedbergb5235a62012-02-21 14:32:24 +02003409 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003410 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003411
3412 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003413 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003414 if (err < 0)
3415 goto failed;
3416
3417 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003418 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003419
Johan Hedbergb5235a62012-02-21 14:32:24 +02003420 goto failed;
3421 }
3422
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003423 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003424 if (!cmd) {
3425 err = -ENOMEM;
3426 goto failed;
3427 }
3428
Johan Hedberg13928972013-03-15 17:07:00 -05003429 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3430
Johan Hedberg890ea892013-03-15 17:06:52 -05003431 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003432
3433 if (lmp_bredr_capable(hdev)) {
3434 update_name(&req);
3435 update_eir(&req);
3436 }
3437
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003438 /* The name is stored in the scan response data and so
3439 * no need to udpate the advertising data here.
3440 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003441 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003442 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003443
Johan Hedberg13928972013-03-15 17:07:00 -05003444 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003445 if (err < 0)
3446 mgmt_pending_remove(cmd);
3447
3448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003449 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003450 return err;
3451}
3452
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003453static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003454 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003455{
Szymon Jancc35938b2011-03-22 13:12:21 +01003456 struct pending_cmd *cmd;
3457 int err;
3458
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003459 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003460
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003461 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003462
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003463 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003464 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003465 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003466 goto unlock;
3467 }
3468
Andre Guedes9a1a1992012-07-24 15:03:48 -03003469 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003470 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003471 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003472 goto unlock;
3473 }
3474
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003475 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003476 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003477 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003478 goto unlock;
3479 }
3480
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003481 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003482 if (!cmd) {
3483 err = -ENOMEM;
3484 goto unlock;
3485 }
3486
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003487 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
3488 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3489 0, NULL);
3490 else
3491 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3492
Szymon Jancc35938b2011-03-22 13:12:21 +01003493 if (err < 0)
3494 mgmt_pending_remove(cmd);
3495
3496unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003497 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003498 return err;
3499}
3500
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003501static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003503{
Szymon Janc2763eda2011-03-22 13:12:22 +01003504 int err;
3505
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003506 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003507
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003508 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003509
Marcel Holtmannec109112014-01-10 02:07:30 -08003510 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3511 struct mgmt_cp_add_remote_oob_data *cp = data;
3512 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003513
Marcel Holtmannec109112014-01-10 02:07:30 -08003514 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
3515 cp->hash, cp->randomizer);
3516 if (err < 0)
3517 status = MGMT_STATUS_FAILED;
3518 else
3519 status = MGMT_STATUS_SUCCESS;
3520
3521 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3522 status, &cp->addr, sizeof(cp->addr));
3523 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3524 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
3525 u8 status;
3526
3527 err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
3528 cp->hash192,
3529 cp->randomizer192,
3530 cp->hash256,
3531 cp->randomizer256);
3532 if (err < 0)
3533 status = MGMT_STATUS_FAILED;
3534 else
3535 status = MGMT_STATUS_SUCCESS;
3536
3537 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3538 status, &cp->addr, sizeof(cp->addr));
3539 } else {
3540 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3541 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3542 MGMT_STATUS_INVALID_PARAMS);
3543 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003544
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003545 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003546 return err;
3547}
3548
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003549static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003550 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003551{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003552 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003553 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003554 int err;
3555
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003556 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003557
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003558 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003559
Johan Hedberg664ce4c2012-02-09 15:44:09 +02003560 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
Szymon Janc2763eda2011-03-22 13:12:22 +01003561 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003562 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003563 else
Szymon Janca6785be2012-12-13 15:11:21 +01003564 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003565
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003566 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003567 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003568
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003569 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003570 return err;
3571}
3572
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003573static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
3574{
3575 struct pending_cmd *cmd;
3576 u8 type;
3577 int err;
3578
3579 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3580
3581 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
3582 if (!cmd)
3583 return -ENOENT;
3584
3585 type = hdev->discovery.type;
3586
3587 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3588 &type, sizeof(type));
3589 mgmt_pending_remove(cmd);
3590
3591 return err;
3592}
3593
Andre Guedes7c307722013-04-30 15:29:28 -03003594static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3595{
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003596 unsigned long timeout = 0;
3597
Andre Guedes7c307722013-04-30 15:29:28 -03003598 BT_DBG("status %d", status);
3599
3600 if (status) {
3601 hci_dev_lock(hdev);
3602 mgmt_start_discovery_failed(hdev, status);
3603 hci_dev_unlock(hdev);
3604 return;
3605 }
3606
3607 hci_dev_lock(hdev);
3608 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
3609 hci_dev_unlock(hdev);
3610
3611 switch (hdev->discovery.type) {
3612 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003613 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003614 break;
3615
3616 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003617 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003618 break;
3619
3620 case DISCOV_TYPE_BREDR:
3621 break;
3622
3623 default:
3624 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
3625 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003626
3627 if (!timeout)
3628 return;
3629
3630 queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003631}
3632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003633static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003635{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003636 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003637 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003638 struct hci_cp_le_set_scan_param param_cp;
3639 struct hci_cp_le_set_scan_enable enable_cp;
3640 struct hci_cp_inquiry inq_cp;
3641 struct hci_request req;
3642 /* General inquiry access code (GIAC) */
3643 u8 lap[3] = { 0x33, 0x8b, 0x9e };
Johan Hedbergd9483942014-02-23 19:42:24 +02003644 u8 status, own_addr_type;
Johan Hedberg14a53662011-04-27 10:29:56 -04003645 int err;
3646
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003647 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003648
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003649 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003650
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003651 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003652 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003653 MGMT_STATUS_NOT_POWERED);
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003654 goto failed;
3655 }
3656
Andre Guedes642be6c2012-03-21 00:03:37 -03003657 if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3658 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3659 MGMT_STATUS_BUSY);
3660 goto failed;
3661 }
3662
Johan Hedbergff9ef572012-01-04 14:23:45 +02003663 if (hdev->discovery.state != DISCOVERY_STOPPED) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003664 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003665 MGMT_STATUS_BUSY);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003666 goto failed;
3667 }
3668
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003669 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003670 if (!cmd) {
3671 err = -ENOMEM;
3672 goto failed;
3673 }
3674
Andre Guedes4aab14e2012-02-17 20:39:36 -03003675 hdev->discovery.type = cp->type;
3676
Andre Guedes7c307722013-04-30 15:29:28 -03003677 hci_req_init(&req, hdev);
3678
Andre Guedes4aab14e2012-02-17 20:39:36 -03003679 switch (hdev->discovery.type) {
Andre Guedesf39799f2012-02-17 20:39:35 -03003680 case DISCOV_TYPE_BREDR:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003681 status = mgmt_bredr_support(hdev);
3682 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003683 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003684 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003685 mgmt_pending_remove(cmd);
3686 goto failed;
3687 }
3688
Andre Guedes7c307722013-04-30 15:29:28 -03003689 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3690 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3691 MGMT_STATUS_BUSY);
3692 mgmt_pending_remove(cmd);
3693 goto failed;
3694 }
3695
3696 hci_inquiry_cache_flush(hdev);
3697
3698 memset(&inq_cp, 0, sizeof(inq_cp));
3699 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
Andre Guedes0d8cc932013-04-30 15:29:31 -03003700 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
Andre Guedes7c307722013-04-30 15:29:28 -03003701 hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
Andre Guedesf39799f2012-02-17 20:39:35 -03003702 break;
3703
3704 case DISCOV_TYPE_LE:
Andre Guedes7c307722013-04-30 15:29:28 -03003705 case DISCOV_TYPE_INTERLEAVED:
Johan Hedberge6fe7982013-10-02 15:45:22 +03003706 status = mgmt_le_support(hdev);
3707 if (status) {
Johan Hedberg04106752013-01-10 14:54:09 +02003708 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03003709 status);
Johan Hedberg04106752013-01-10 14:54:09 +02003710 mgmt_pending_remove(cmd);
3711 goto failed;
3712 }
3713
Andre Guedes7c307722013-04-30 15:29:28 -03003714 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Johan Hedberg56f87902013-10-02 13:43:13 +03003715 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Johan Hedberg04106752013-01-10 14:54:09 +02003716 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3717 MGMT_STATUS_NOT_SUPPORTED);
3718 mgmt_pending_remove(cmd);
3719 goto failed;
3720 }
3721
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02003722 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
Andre Guedes7c307722013-04-30 15:29:28 -03003723 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3724 MGMT_STATUS_REJECTED);
3725 mgmt_pending_remove(cmd);
3726 goto failed;
3727 }
3728
Andre Guedesc54c3862014-02-26 20:21:50 -03003729 /* If controller is scanning, it means the background scanning
3730 * is running. Thus, we should temporarily stop it in order to
3731 * set the discovery scanning parameters.
3732 */
3733 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3734 hci_req_add_le_scan_disable(&req);
Andre Guedes7c307722013-04-30 15:29:28 -03003735
3736 memset(&param_cp, 0, sizeof(param_cp));
Johan Hedbergd9483942014-02-23 19:42:24 +02003737
Marcel Holtmann94b1fc92014-02-23 20:25:54 -08003738 /* All active scans will be done with either a resolvable
3739 * private address (when privacy feature has been enabled)
3740 * or unresolvable private address.
3741 */
3742 err = hci_update_random_address(&req, true, &own_addr_type);
Johan Hedbergd9483942014-02-23 19:42:24 +02003743 if (err < 0) {
3744 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3745 MGMT_STATUS_FAILED);
3746 mgmt_pending_remove(cmd);
3747 goto failed;
3748 }
3749
Andre Guedes7c307722013-04-30 15:29:28 -03003750 param_cp.type = LE_SCAN_ACTIVE;
Andre Guedes0d8cc932013-04-30 15:29:31 -03003751 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3752 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
Johan Hedbergd9483942014-02-23 19:42:24 +02003753 param_cp.own_address_type = own_addr_type;
Andre Guedes7c307722013-04-30 15:29:28 -03003754 hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3755 &param_cp);
3756
3757 memset(&enable_cp, 0, sizeof(enable_cp));
3758 enable_cp.enable = LE_SCAN_ENABLE;
3759 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3760 hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3761 &enable_cp);
Andre Guedes5e0452c2012-02-17 20:39:38 -03003762 break;
3763
Andre Guedesf39799f2012-02-17 20:39:35 -03003764 default:
Johan Hedberg04106752013-01-10 14:54:09 +02003765 err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3766 MGMT_STATUS_INVALID_PARAMS);
3767 mgmt_pending_remove(cmd);
3768 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003769 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003770
Andre Guedes7c307722013-04-30 15:29:28 -03003771 err = hci_req_run(&req, start_discovery_complete);
Johan Hedberg14a53662011-04-27 10:29:56 -04003772 if (err < 0)
3773 mgmt_pending_remove(cmd);
Johan Hedbergff9ef572012-01-04 14:23:45 +02003774 else
3775 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003776
3777failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003778 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003779 return err;
3780}
3781
Andre Guedes1183fdc2013-04-30 15:29:35 -03003782static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
3783{
3784 struct pending_cmd *cmd;
3785 int err;
3786
3787 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
3788 if (!cmd)
3789 return -ENOENT;
3790
3791 err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
3792 &hdev->discovery.type, sizeof(hdev->discovery.type));
3793 mgmt_pending_remove(cmd);
3794
3795 return err;
3796}
3797
Andre Guedes0e05bba2013-04-30 15:29:33 -03003798static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
3799{
3800 BT_DBG("status %d", status);
3801
3802 hci_dev_lock(hdev);
3803
3804 if (status) {
3805 mgmt_stop_discovery_failed(hdev, status);
3806 goto unlock;
3807 }
3808
3809 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3810
3811unlock:
3812 hci_dev_unlock(hdev);
3813}
3814
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003815static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003816 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003817{
Johan Hedbergd9306502012-02-20 23:25:18 +02003818 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003819 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03003820 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04003821 int err;
3822
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003823 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003824
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003825 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003826
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003827 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003828 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003829 MGMT_STATUS_REJECTED, &mgmt_cp->type,
3830 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02003831 goto unlock;
3832 }
3833
3834 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003835 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003836 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
3837 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003838 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02003839 }
3840
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003841 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003842 if (!cmd) {
3843 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003844 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04003845 }
3846
Andre Guedes0e05bba2013-04-30 15:29:33 -03003847 hci_req_init(&req, hdev);
3848
Johan Hedberg21a60d32014-06-10 14:05:58 +03003849 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003850
Johan Hedberg21a60d32014-06-10 14:05:58 +03003851 err = hci_req_run(&req, stop_discovery_complete);
3852 if (!err) {
3853 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03003854 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003855 }
3856
Johan Hedberg21a60d32014-06-10 14:05:58 +03003857 mgmt_pending_remove(cmd);
3858
3859 /* If no HCI commands were sent we're done */
3860 if (err == -ENODATA) {
3861 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
3862 &mgmt_cp->type, sizeof(mgmt_cp->type));
3863 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3864 }
Johan Hedberg14a53662011-04-27 10:29:56 -04003865
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003866unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003867 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003868 return err;
3869}
3870
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003871static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003872 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02003873{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003874 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003875 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02003876 int err;
3877
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003878 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003879
Johan Hedberg561aafb2012-01-04 13:31:59 +02003880 hci_dev_lock(hdev);
3881
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003882 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003883 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3884 MGMT_STATUS_FAILED, &cp->addr,
3885 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02003886 goto failed;
3887 }
3888
Johan Hedberga198e7b2012-02-17 14:27:06 +02003889 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003890 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01003891 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
3892 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
3893 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003894 goto failed;
3895 }
3896
3897 if (cp->name_known) {
3898 e->name_state = NAME_KNOWN;
3899 list_del(&e->list);
3900 } else {
3901 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02003902 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003903 }
3904
Johan Hedberge3846622013-01-09 15:29:33 +02003905 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
3906 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02003907
3908failed:
3909 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02003910 return err;
3911}
3912
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003913static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003914 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003915{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003916 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003917 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003918 int err;
3919
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003920 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003921
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003922 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003923 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
3924 MGMT_STATUS_INVALID_PARAMS,
3925 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003926
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003927 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003928
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003929 err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003930 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003931 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003932 goto done;
3933 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003934
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003935 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3936 sk);
3937 status = MGMT_STATUS_SUCCESS;
3938
3939done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003940 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003941 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003942
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003943 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003944
3945 return err;
3946}
3947
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003948static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003949 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03003950{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003951 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003952 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03003953 int err;
3954
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003955 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03003956
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003957 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02003958 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
3959 MGMT_STATUS_INVALID_PARAMS,
3960 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003961
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003962 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03003963
Johan Hedberg88c1fe42012-02-09 15:56:11 +02003964 err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003965 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003966 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003967 goto done;
3968 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02003969
Johan Hedberg2a8357f2014-07-01 22:09:47 +03003970 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
3971 sk);
3972 status = MGMT_STATUS_SUCCESS;
3973
3974done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003975 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003976 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03003977
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003978 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03003979
3980 return err;
3981}
3982
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003983static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
3984 u16 len)
3985{
3986 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05003987 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003988 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01003989 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003990
3991 BT_DBG("%s", hdev->name);
3992
Szymon Jancc72d4b82012-03-16 16:02:57 +01003993 source = __le16_to_cpu(cp->source);
3994
3995 if (source > 0x0002)
3996 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
3997 MGMT_STATUS_INVALID_PARAMS);
3998
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07003999 hci_dev_lock(hdev);
4000
Szymon Jancc72d4b82012-03-16 16:02:57 +01004001 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004002 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4003 hdev->devid_product = __le16_to_cpu(cp->product);
4004 hdev->devid_version = __le16_to_cpu(cp->version);
4005
4006 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4007
Johan Hedberg890ea892013-03-15 17:06:52 -05004008 hci_req_init(&req, hdev);
4009 update_eir(&req);
4010 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004011
4012 hci_dev_unlock(hdev);
4013
4014 return err;
4015}
4016
Johan Hedberg4375f102013-09-25 13:26:10 +03004017static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4018{
4019 struct cmd_lookup match = { NULL, hdev };
4020
4021 if (status) {
4022 u8 mgmt_err = mgmt_status(status);
4023
4024 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4025 cmd_status_rsp, &mgmt_err);
4026 return;
4027 }
4028
4029 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4030 &match);
4031
4032 new_settings(hdev, match.sk);
4033
4034 if (match.sk)
4035 sock_put(match.sk);
4036}
4037
Marcel Holtmann21b51872013-10-10 09:47:53 -07004038static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4039 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004040{
4041 struct mgmt_mode *cp = data;
4042 struct pending_cmd *cmd;
4043 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004044 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004045 int err;
4046
4047 BT_DBG("request for %s", hdev->name);
4048
Johan Hedberge6fe7982013-10-02 15:45:22 +03004049 status = mgmt_le_support(hdev);
4050 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004051 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004052 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004053
4054 if (cp->val != 0x00 && cp->val != 0x01)
4055 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4056 MGMT_STATUS_INVALID_PARAMS);
4057
4058 hci_dev_lock(hdev);
4059
4060 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004061 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004062
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004063 /* The following conditions are ones which mean that we should
4064 * not do any HCI communication but directly send a mgmt
4065 * response to user space (after toggling the flag if
4066 * necessary).
4067 */
4068 if (!hdev_is_powered(hdev) || val == enabled ||
Marcel Holtmannb145edc2013-10-10 09:47:54 -07004069 hci_conn_num(hdev, LE_LINK) > 0) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004070 bool changed = false;
4071
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004072 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4073 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004074 changed = true;
4075 }
4076
4077 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4078 if (err < 0)
4079 goto unlock;
4080
4081 if (changed)
4082 err = new_settings(hdev, sk);
4083
4084 goto unlock;
4085 }
4086
4087 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4088 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4089 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4090 MGMT_STATUS_BUSY);
4091 goto unlock;
4092 }
4093
4094 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4095 if (!cmd) {
4096 err = -ENOMEM;
4097 goto unlock;
4098 }
4099
4100 hci_req_init(&req, hdev);
4101
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004102 if (val)
4103 enable_advertising(&req);
4104 else
4105 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004106
4107 err = hci_req_run(&req, set_advertising_complete);
4108 if (err < 0)
4109 mgmt_pending_remove(cmd);
4110
4111unlock:
4112 hci_dev_unlock(hdev);
4113 return err;
4114}
4115
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004116static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4117 void *data, u16 len)
4118{
4119 struct mgmt_cp_set_static_address *cp = data;
4120 int err;
4121
4122 BT_DBG("%s", hdev->name);
4123
Marcel Holtmann62af4442013-10-02 22:10:32 -07004124 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004125 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004126 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004127
4128 if (hdev_is_powered(hdev))
4129 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4130 MGMT_STATUS_REJECTED);
4131
4132 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4133 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4134 return cmd_status(sk, hdev->id,
4135 MGMT_OP_SET_STATIC_ADDRESS,
4136 MGMT_STATUS_INVALID_PARAMS);
4137
4138 /* Two most significant bits shall be set */
4139 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4140 return cmd_status(sk, hdev->id,
4141 MGMT_OP_SET_STATIC_ADDRESS,
4142 MGMT_STATUS_INVALID_PARAMS);
4143 }
4144
4145 hci_dev_lock(hdev);
4146
4147 bacpy(&hdev->static_addr, &cp->bdaddr);
4148
4149 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4150
4151 hci_dev_unlock(hdev);
4152
4153 return err;
4154}
4155
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004156static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4157 void *data, u16 len)
4158{
4159 struct mgmt_cp_set_scan_params *cp = data;
4160 __u16 interval, window;
4161 int err;
4162
4163 BT_DBG("%s", hdev->name);
4164
4165 if (!lmp_le_capable(hdev))
4166 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4167 MGMT_STATUS_NOT_SUPPORTED);
4168
4169 interval = __le16_to_cpu(cp->interval);
4170
4171 if (interval < 0x0004 || interval > 0x4000)
4172 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4173 MGMT_STATUS_INVALID_PARAMS);
4174
4175 window = __le16_to_cpu(cp->window);
4176
4177 if (window < 0x0004 || window > 0x4000)
4178 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4179 MGMT_STATUS_INVALID_PARAMS);
4180
Marcel Holtmann899e1072013-10-14 09:55:32 -07004181 if (window > interval)
4182 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4183 MGMT_STATUS_INVALID_PARAMS);
4184
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004185 hci_dev_lock(hdev);
4186
4187 hdev->le_scan_interval = interval;
4188 hdev->le_scan_window = window;
4189
4190 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4191
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004192 /* If background scan is running, restart it so new parameters are
4193 * loaded.
4194 */
4195 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4196 hdev->discovery.state == DISCOVERY_STOPPED) {
4197 struct hci_request req;
4198
4199 hci_req_init(&req, hdev);
4200
4201 hci_req_add_le_scan_disable(&req);
4202 hci_req_add_le_passive_scan(&req);
4203
4204 hci_req_run(&req, NULL);
4205 }
4206
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004207 hci_dev_unlock(hdev);
4208
4209 return err;
4210}
4211
Johan Hedberg33e38b32013-03-15 17:07:05 -05004212static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4213{
4214 struct pending_cmd *cmd;
4215
4216 BT_DBG("status 0x%02x", status);
4217
4218 hci_dev_lock(hdev);
4219
4220 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4221 if (!cmd)
4222 goto unlock;
4223
4224 if (status) {
4225 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4226 mgmt_status(status));
4227 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004228 struct mgmt_mode *cp = cmd->param;
4229
4230 if (cp->val)
4231 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4232 else
4233 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4234
Johan Hedberg33e38b32013-03-15 17:07:05 -05004235 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4236 new_settings(hdev, cmd->sk);
4237 }
4238
4239 mgmt_pending_remove(cmd);
4240
4241unlock:
4242 hci_dev_unlock(hdev);
4243}
4244
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004245static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004246 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004247{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004248 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004249 struct pending_cmd *cmd;
4250 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004251 int err;
4252
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004253 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004254
Johan Hedberg56f87902013-10-02 13:43:13 +03004255 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4256 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004257 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4258 MGMT_STATUS_NOT_SUPPORTED);
4259
Johan Hedberga7e80f22013-01-09 16:05:19 +02004260 if (cp->val != 0x00 && cp->val != 0x01)
4261 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4262 MGMT_STATUS_INVALID_PARAMS);
4263
Johan Hedberg5400c042012-02-21 16:40:33 +02004264 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004265 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004266 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004267
4268 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004269 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004270 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004271
4272 hci_dev_lock(hdev);
4273
Johan Hedberg05cbf292013-03-15 17:07:07 -05004274 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4275 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4276 MGMT_STATUS_BUSY);
4277 goto unlock;
4278 }
4279
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004280 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4281 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4282 hdev);
4283 goto unlock;
4284 }
4285
Johan Hedberg33e38b32013-03-15 17:07:05 -05004286 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4287 data, len);
4288 if (!cmd) {
4289 err = -ENOMEM;
4290 goto unlock;
4291 }
4292
4293 hci_req_init(&req, hdev);
4294
Johan Hedberg406d7802013-03-15 17:07:09 -05004295 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004296
4297 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004298 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004299 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004300 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004301 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004302 }
4303
Johan Hedberg33e38b32013-03-15 17:07:05 -05004304unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004305 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004306
Antti Julkuf6422ec2011-06-22 13:11:56 +03004307 return err;
4308}
4309
Johan Hedberg67e5a7a2013-10-14 21:15:25 +03004310static void set_bredr_scan(struct hci_request *req)
4311{
4312 struct hci_dev *hdev = req->hdev;
4313 u8 scan = 0;
4314
4315 /* Ensure that fast connectable is disabled. This function will
4316 * not do anything if the page scan parameters are already what
4317 * they should be.
4318 */
4319 write_fast_connectable(req, false);
4320
4321 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4322 scan |= SCAN_PAGE;
4323 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
4324 scan |= SCAN_INQUIRY;
4325
4326 if (scan)
4327 hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
4328}
4329
Johan Hedberg0663ca22013-10-02 13:43:14 +03004330static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4331{
4332 struct pending_cmd *cmd;
4333
4334 BT_DBG("status 0x%02x", status);
4335
4336 hci_dev_lock(hdev);
4337
4338 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4339 if (!cmd)
4340 goto unlock;
4341
4342 if (status) {
4343 u8 mgmt_err = mgmt_status(status);
4344
4345 /* We need to restore the flag if related HCI commands
4346 * failed.
4347 */
4348 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4349
4350 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4351 } else {
4352 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4353 new_settings(hdev, cmd->sk);
4354 }
4355
4356 mgmt_pending_remove(cmd);
4357
4358unlock:
4359 hci_dev_unlock(hdev);
4360}
4361
4362static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4363{
4364 struct mgmt_mode *cp = data;
4365 struct pending_cmd *cmd;
4366 struct hci_request req;
4367 int err;
4368
4369 BT_DBG("request for %s", hdev->name);
4370
4371 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4372 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4373 MGMT_STATUS_NOT_SUPPORTED);
4374
4375 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4376 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4377 MGMT_STATUS_REJECTED);
4378
4379 if (cp->val != 0x00 && cp->val != 0x01)
4380 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4381 MGMT_STATUS_INVALID_PARAMS);
4382
4383 hci_dev_lock(hdev);
4384
4385 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4386 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4387 goto unlock;
4388 }
4389
4390 if (!hdev_is_powered(hdev)) {
4391 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004392 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4393 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4394 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4395 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4396 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4397 }
4398
4399 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4400
4401 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4402 if (err < 0)
4403 goto unlock;
4404
4405 err = new_settings(hdev, sk);
4406 goto unlock;
4407 }
4408
4409 /* Reject disabling when powered on */
4410 if (!cp->val) {
4411 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4412 MGMT_STATUS_REJECTED);
4413 goto unlock;
4414 }
4415
4416 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4417 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4418 MGMT_STATUS_BUSY);
4419 goto unlock;
4420 }
4421
4422 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4423 if (!cmd) {
4424 err = -ENOMEM;
4425 goto unlock;
4426 }
4427
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004428 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004429 * generates the correct flags.
4430 */
4431 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4432
4433 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004434
4435 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
4436 set_bredr_scan(&req);
4437
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004438 /* Since only the advertising data flags will change, there
4439 * is no need to update the scan response data.
4440 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004441 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004442
Johan Hedberg0663ca22013-10-02 13:43:14 +03004443 err = hci_req_run(&req, set_bredr_complete);
4444 if (err < 0)
4445 mgmt_pending_remove(cmd);
4446
4447unlock:
4448 hci_dev_unlock(hdev);
4449 return err;
4450}
4451
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004452static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4453 void *data, u16 len)
4454{
4455 struct mgmt_mode *cp = data;
4456 struct pending_cmd *cmd;
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004457 u8 val, status;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004458 int err;
4459
4460 BT_DBG("request for %s", hdev->name);
4461
4462 status = mgmt_bredr_support(hdev);
4463 if (status)
4464 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4465 status);
4466
Marcel Holtmann5afeac12014-01-10 02:07:27 -08004467 if (!lmp_sc_capable(hdev) &&
Marcel Holtmann111902f2014-06-21 04:53:17 +02004468 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004469 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4470 MGMT_STATUS_NOT_SUPPORTED);
4471
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004472 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004473 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4474 MGMT_STATUS_INVALID_PARAMS);
4475
4476 hci_dev_lock(hdev);
4477
4478 if (!hdev_is_powered(hdev)) {
4479 bool changed;
4480
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004481 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004482 changed = !test_and_set_bit(HCI_SC_ENABLED,
4483 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004484 if (cp->val == 0x02)
4485 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4486 else
4487 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4488 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004489 changed = test_and_clear_bit(HCI_SC_ENABLED,
4490 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004491 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4492 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004493
4494 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4495 if (err < 0)
4496 goto failed;
4497
4498 if (changed)
4499 err = new_settings(hdev, sk);
4500
4501 goto failed;
4502 }
4503
4504 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4505 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4506 MGMT_STATUS_BUSY);
4507 goto failed;
4508 }
4509
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004510 val = !!cp->val;
4511
4512 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4513 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004514 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4515 goto failed;
4516 }
4517
4518 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4519 if (!cmd) {
4520 err = -ENOMEM;
4521 goto failed;
4522 }
4523
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004524 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004525 if (err < 0) {
4526 mgmt_pending_remove(cmd);
4527 goto failed;
4528 }
4529
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004530 if (cp->val == 0x02)
4531 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4532 else
4533 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4534
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004535failed:
4536 hci_dev_unlock(hdev);
4537 return err;
4538}
4539
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004540static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4541 void *data, u16 len)
4542{
4543 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004544 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004545 int err;
4546
4547 BT_DBG("request for %s", hdev->name);
4548
Johan Hedbergb97109792014-06-24 14:00:28 +03004549 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004550 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4551 MGMT_STATUS_INVALID_PARAMS);
4552
4553 hci_dev_lock(hdev);
4554
4555 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004556 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4557 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004558 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004559 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4560 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004561
Johan Hedbergb97109792014-06-24 14:00:28 +03004562 if (cp->val == 0x02)
4563 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4564 &hdev->dev_flags);
4565 else
4566 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4567 &hdev->dev_flags);
4568
4569 if (hdev_is_powered(hdev) && use_changed &&
4570 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4571 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4572 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4573 sizeof(mode), &mode);
4574 }
4575
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004576 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4577 if (err < 0)
4578 goto unlock;
4579
4580 if (changed)
4581 err = new_settings(hdev, sk);
4582
4583unlock:
4584 hci_dev_unlock(hdev);
4585 return err;
4586}
4587
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004588static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4589 u16 len)
4590{
4591 struct mgmt_cp_set_privacy *cp = cp_data;
4592 bool changed;
4593 int err;
4594
4595 BT_DBG("request for %s", hdev->name);
4596
4597 if (!lmp_le_capable(hdev))
4598 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4599 MGMT_STATUS_NOT_SUPPORTED);
4600
4601 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4602 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4603 MGMT_STATUS_INVALID_PARAMS);
4604
4605 if (hdev_is_powered(hdev))
4606 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4607 MGMT_STATUS_REJECTED);
4608
4609 hci_dev_lock(hdev);
4610
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004611 /* If user space supports this command it is also expected to
4612 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4613 */
4614 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4615
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004616 if (cp->privacy) {
4617 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4618 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4619 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4620 } else {
4621 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4622 memset(hdev->irk, 0, sizeof(hdev->irk));
4623 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4624 }
4625
4626 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4627 if (err < 0)
4628 goto unlock;
4629
4630 if (changed)
4631 err = new_settings(hdev, sk);
4632
4633unlock:
4634 hci_dev_unlock(hdev);
4635 return err;
4636}
4637
Johan Hedberg41edf162014-02-18 10:19:35 +02004638static bool irk_is_valid(struct mgmt_irk_info *irk)
4639{
4640 switch (irk->addr.type) {
4641 case BDADDR_LE_PUBLIC:
4642 return true;
4643
4644 case BDADDR_LE_RANDOM:
4645 /* Two most significant bits shall be set */
4646 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4647 return false;
4648 return true;
4649 }
4650
4651 return false;
4652}
4653
4654static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4655 u16 len)
4656{
4657 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004658 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4659 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004660 u16 irk_count, expected_len;
4661 int i, err;
4662
4663 BT_DBG("request for %s", hdev->name);
4664
4665 if (!lmp_le_capable(hdev))
4666 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4667 MGMT_STATUS_NOT_SUPPORTED);
4668
4669 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004670 if (irk_count > max_irk_count) {
4671 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4672 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4673 MGMT_STATUS_INVALID_PARAMS);
4674 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004675
4676 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4677 if (expected_len != len) {
4678 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004679 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004680 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4681 MGMT_STATUS_INVALID_PARAMS);
4682 }
4683
4684 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4685
4686 for (i = 0; i < irk_count; i++) {
4687 struct mgmt_irk_info *key = &cp->irks[i];
4688
4689 if (!irk_is_valid(key))
4690 return cmd_status(sk, hdev->id,
4691 MGMT_OP_LOAD_IRKS,
4692 MGMT_STATUS_INVALID_PARAMS);
4693 }
4694
4695 hci_dev_lock(hdev);
4696
4697 hci_smp_irks_clear(hdev);
4698
4699 for (i = 0; i < irk_count; i++) {
4700 struct mgmt_irk_info *irk = &cp->irks[i];
4701 u8 addr_type;
4702
4703 if (irk->addr.type == BDADDR_LE_PUBLIC)
4704 addr_type = ADDR_LE_DEV_PUBLIC;
4705 else
4706 addr_type = ADDR_LE_DEV_RANDOM;
4707
4708 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4709 BDADDR_ANY);
4710 }
4711
4712 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4713
4714 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4715
4716 hci_dev_unlock(hdev);
4717
4718 return err;
4719}
4720
Johan Hedberg3f706b72013-01-20 14:27:16 +02004721static bool ltk_is_valid(struct mgmt_ltk_info *key)
4722{
4723 if (key->master != 0x00 && key->master != 0x01)
4724 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004725
4726 switch (key->addr.type) {
4727 case BDADDR_LE_PUBLIC:
4728 return true;
4729
4730 case BDADDR_LE_RANDOM:
4731 /* Two most significant bits shall be set */
4732 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4733 return false;
4734 return true;
4735 }
4736
4737 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004738}
4739
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004740static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004741 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004742{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004743 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004744 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4745 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004746 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004747 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004748
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004749 BT_DBG("request for %s", hdev->name);
4750
4751 if (!lmp_le_capable(hdev))
4752 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4753 MGMT_STATUS_NOT_SUPPORTED);
4754
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004755 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004756 if (key_count > max_key_count) {
4757 BT_ERR("load_ltks: too big key_count value %u", key_count);
4758 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4759 MGMT_STATUS_INVALID_PARAMS);
4760 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004761
4762 expected_len = sizeof(*cp) + key_count *
4763 sizeof(struct mgmt_ltk_info);
4764 if (expected_len != len) {
4765 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004766 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004767 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004768 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004769 }
4770
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004771 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004772
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004773 for (i = 0; i < key_count; i++) {
4774 struct mgmt_ltk_info *key = &cp->keys[i];
4775
Johan Hedberg3f706b72013-01-20 14:27:16 +02004776 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004777 return cmd_status(sk, hdev->id,
4778 MGMT_OP_LOAD_LONG_TERM_KEYS,
4779 MGMT_STATUS_INVALID_PARAMS);
4780 }
4781
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004782 hci_dev_lock(hdev);
4783
4784 hci_smp_ltks_clear(hdev);
4785
4786 for (i = 0; i < key_count; i++) {
4787 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03004788 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07004789
4790 if (key->addr.type == BDADDR_LE_PUBLIC)
4791 addr_type = ADDR_LE_DEV_PUBLIC;
4792 else
4793 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004794
4795 if (key->master)
Johan Hedberg2ceba532014-06-16 19:25:16 +03004796 type = SMP_LTK;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004797 else
Johan Hedberg2ceba532014-06-16 19:25:16 +03004798 type = SMP_LTK_SLAVE;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004799
Johan Hedberg61b43352014-05-29 19:36:53 +03004800 switch (key->type) {
4801 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004802 authenticated = 0x00;
Johan Hedberg61b43352014-05-29 19:36:53 +03004803 break;
4804 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03004805 authenticated = 0x01;
Johan Hedberg61b43352014-05-29 19:36:53 +03004806 break;
4807 default:
4808 continue;
4809 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03004810
Johan Hedberg35d70272014-02-19 14:57:47 +02004811 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03004812 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02004813 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004814 }
4815
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004816 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
4817 NULL, 0);
4818
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004819 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004820
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004821 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004822}
4823
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004824struct cmd_conn_lookup {
4825 struct hci_conn *conn;
4826 bool valid_tx_power;
4827 u8 mgmt_status;
4828};
4829
4830static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
4831{
4832 struct cmd_conn_lookup *match = data;
4833 struct mgmt_cp_get_conn_info *cp;
4834 struct mgmt_rp_get_conn_info rp;
4835 struct hci_conn *conn = cmd->user_data;
4836
4837 if (conn != match->conn)
4838 return;
4839
4840 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
4841
4842 memset(&rp, 0, sizeof(rp));
4843 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4844 rp.addr.type = cp->addr.type;
4845
4846 if (!match->mgmt_status) {
4847 rp.rssi = conn->rssi;
4848
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004849 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004850 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004851 rp.max_tx_power = conn->max_tx_power;
4852 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004853 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004854 rp.max_tx_power = HCI_TX_POWER_INVALID;
4855 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004856 }
4857
4858 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
4859 match->mgmt_status, &rp, sizeof(rp));
4860
4861 hci_conn_drop(conn);
4862
4863 mgmt_pending_remove(cmd);
4864}
4865
4866static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
4867{
4868 struct hci_cp_read_rssi *cp;
4869 struct hci_conn *conn;
4870 struct cmd_conn_lookup match;
4871 u16 handle;
4872
4873 BT_DBG("status 0x%02x", status);
4874
4875 hci_dev_lock(hdev);
4876
4877 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004878 * otherwise we assume it's not valid. At the moment we assume that
4879 * either both or none of current and max values are valid to keep code
4880 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004881 */
4882 match.valid_tx_power = !status;
4883
4884 /* Commands sent in request are either Read RSSI or Read Transmit Power
4885 * Level so we check which one was last sent to retrieve connection
4886 * handle. Both commands have handle as first parameter so it's safe to
4887 * cast data on the same command struct.
4888 *
4889 * First command sent is always Read RSSI and we fail only if it fails.
4890 * In other case we simply override error to indicate success as we
4891 * already remembered if TX power value is actually valid.
4892 */
4893 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
4894 if (!cp) {
4895 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
4896 status = 0;
4897 }
4898
4899 if (!cp) {
4900 BT_ERR("invalid sent_cmd in response");
4901 goto unlock;
4902 }
4903
4904 handle = __le16_to_cpu(cp->handle);
4905 conn = hci_conn_hash_lookup_handle(hdev, handle);
4906 if (!conn) {
4907 BT_ERR("unknown handle (%d) in response", handle);
4908 goto unlock;
4909 }
4910
4911 match.conn = conn;
4912 match.mgmt_status = mgmt_status(status);
4913
4914 /* Cache refresh is complete, now reply for mgmt request for given
4915 * connection only.
4916 */
4917 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
4918 get_conn_info_complete, &match);
4919
4920unlock:
4921 hci_dev_unlock(hdev);
4922}
4923
4924static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
4925 u16 len)
4926{
4927 struct mgmt_cp_get_conn_info *cp = data;
4928 struct mgmt_rp_get_conn_info rp;
4929 struct hci_conn *conn;
4930 unsigned long conn_info_age;
4931 int err = 0;
4932
4933 BT_DBG("%s", hdev->name);
4934
4935 memset(&rp, 0, sizeof(rp));
4936 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
4937 rp.addr.type = cp->addr.type;
4938
4939 if (!bdaddr_type_is_valid(cp->addr.type))
4940 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4941 MGMT_STATUS_INVALID_PARAMS,
4942 &rp, sizeof(rp));
4943
4944 hci_dev_lock(hdev);
4945
4946 if (!hdev_is_powered(hdev)) {
4947 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4948 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
4949 goto unlock;
4950 }
4951
4952 if (cp->addr.type == BDADDR_BREDR)
4953 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
4954 &cp->addr.bdaddr);
4955 else
4956 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
4957
4958 if (!conn || conn->state != BT_CONNECTED) {
4959 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
4960 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
4961 goto unlock;
4962 }
4963
4964 /* To avoid client trying to guess when to poll again for information we
4965 * calculate conn info age as random value between min/max set in hdev.
4966 */
4967 conn_info_age = hdev->conn_info_min_age +
4968 prandom_u32_max(hdev->conn_info_max_age -
4969 hdev->conn_info_min_age);
4970
4971 /* Query controller to refresh cached values if they are too old or were
4972 * never read.
4973 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02004974 if (time_after(jiffies, conn->conn_info_timestamp +
4975 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004976 !conn->conn_info_timestamp) {
4977 struct hci_request req;
4978 struct hci_cp_read_tx_power req_txp_cp;
4979 struct hci_cp_read_rssi req_rssi_cp;
4980 struct pending_cmd *cmd;
4981
4982 hci_req_init(&req, hdev);
4983 req_rssi_cp.handle = cpu_to_le16(conn->handle);
4984 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
4985 &req_rssi_cp);
4986
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02004987 /* For LE links TX power does not change thus we don't need to
4988 * query for it once value is known.
4989 */
4990 if (!bdaddr_type_is_le(cp->addr.type) ||
4991 conn->tx_power == HCI_TX_POWER_INVALID) {
4992 req_txp_cp.handle = cpu_to_le16(conn->handle);
4993 req_txp_cp.type = 0x00;
4994 hci_req_add(&req, HCI_OP_READ_TX_POWER,
4995 sizeof(req_txp_cp), &req_txp_cp);
4996 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02004997
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02004998 /* Max TX power needs to be read only once per connection */
4999 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5000 req_txp_cp.handle = cpu_to_le16(conn->handle);
5001 req_txp_cp.type = 0x01;
5002 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5003 sizeof(req_txp_cp), &req_txp_cp);
5004 }
5005
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005006 err = hci_req_run(&req, conn_info_refresh_complete);
5007 if (err < 0)
5008 goto unlock;
5009
5010 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5011 data, len);
5012 if (!cmd) {
5013 err = -ENOMEM;
5014 goto unlock;
5015 }
5016
5017 hci_conn_hold(conn);
5018 cmd->user_data = conn;
5019
5020 conn->conn_info_timestamp = jiffies;
5021 } else {
5022 /* Cache is valid, just reply with values cached in hci_conn */
5023 rp.rssi = conn->rssi;
5024 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005025 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005026
5027 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5028 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5029 }
5030
5031unlock:
5032 hci_dev_unlock(hdev);
5033 return err;
5034}
5035
Johan Hedberg95868422014-06-28 17:54:07 +03005036static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5037{
5038 struct mgmt_cp_get_clock_info *cp;
5039 struct mgmt_rp_get_clock_info rp;
5040 struct hci_cp_read_clock *hci_cp;
5041 struct pending_cmd *cmd;
5042 struct hci_conn *conn;
5043
5044 BT_DBG("%s status %u", hdev->name, status);
5045
5046 hci_dev_lock(hdev);
5047
5048 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5049 if (!hci_cp)
5050 goto unlock;
5051
5052 if (hci_cp->which) {
5053 u16 handle = __le16_to_cpu(hci_cp->handle);
5054 conn = hci_conn_hash_lookup_handle(hdev, handle);
5055 } else {
5056 conn = NULL;
5057 }
5058
5059 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5060 if (!cmd)
5061 goto unlock;
5062
5063 cp = cmd->param;
5064
5065 memset(&rp, 0, sizeof(rp));
5066 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5067
5068 if (status)
5069 goto send_rsp;
5070
5071 rp.local_clock = cpu_to_le32(hdev->clock);
5072
5073 if (conn) {
5074 rp.piconet_clock = cpu_to_le32(conn->clock);
5075 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5076 }
5077
5078send_rsp:
5079 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5080 &rp, sizeof(rp));
5081 mgmt_pending_remove(cmd);
5082 if (conn)
5083 hci_conn_drop(conn);
5084
5085unlock:
5086 hci_dev_unlock(hdev);
5087}
5088
5089static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5090 u16 len)
5091{
5092 struct mgmt_cp_get_clock_info *cp = data;
5093 struct mgmt_rp_get_clock_info rp;
5094 struct hci_cp_read_clock hci_cp;
5095 struct pending_cmd *cmd;
5096 struct hci_request req;
5097 struct hci_conn *conn;
5098 int err;
5099
5100 BT_DBG("%s", hdev->name);
5101
5102 memset(&rp, 0, sizeof(rp));
5103 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5104 rp.addr.type = cp->addr.type;
5105
5106 if (cp->addr.type != BDADDR_BREDR)
5107 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5108 MGMT_STATUS_INVALID_PARAMS,
5109 &rp, sizeof(rp));
5110
5111 hci_dev_lock(hdev);
5112
5113 if (!hdev_is_powered(hdev)) {
5114 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5115 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5116 goto unlock;
5117 }
5118
5119 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5120 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5121 &cp->addr.bdaddr);
5122 if (!conn || conn->state != BT_CONNECTED) {
5123 err = cmd_complete(sk, hdev->id,
5124 MGMT_OP_GET_CLOCK_INFO,
5125 MGMT_STATUS_NOT_CONNECTED,
5126 &rp, sizeof(rp));
5127 goto unlock;
5128 }
5129 } else {
5130 conn = NULL;
5131 }
5132
5133 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5134 if (!cmd) {
5135 err = -ENOMEM;
5136 goto unlock;
5137 }
5138
5139 hci_req_init(&req, hdev);
5140
5141 memset(&hci_cp, 0, sizeof(hci_cp));
5142 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5143
5144 if (conn) {
5145 hci_conn_hold(conn);
5146 cmd->user_data = conn;
5147
5148 hci_cp.handle = cpu_to_le16(conn->handle);
5149 hci_cp.which = 0x01; /* Piconet clock */
5150 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5151 }
5152
5153 err = hci_req_run(&req, get_clock_info_complete);
5154 if (err < 0)
5155 mgmt_pending_remove(cmd);
5156
5157unlock:
5158 hci_dev_unlock(hdev);
5159 return err;
5160}
5161
Marcel Holtmann8afef092014-06-29 22:28:34 +02005162static void device_added(struct sock *sk, struct hci_dev *hdev,
5163 bdaddr_t *bdaddr, u8 type, u8 action)
5164{
5165 struct mgmt_ev_device_added ev;
5166
5167 bacpy(&ev.addr.bdaddr, bdaddr);
5168 ev.addr.type = type;
5169 ev.action = action;
5170
5171 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5172}
5173
Marcel Holtmann2faade52014-06-29 19:44:03 +02005174static int add_device(struct sock *sk, struct hci_dev *hdev,
5175 void *data, u16 len)
5176{
5177 struct mgmt_cp_add_device *cp = data;
5178 u8 auto_conn, addr_type;
5179 int err;
5180
5181 BT_DBG("%s", hdev->name);
5182
5183 if (!bdaddr_type_is_le(cp->addr.type) ||
5184 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5185 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5186 MGMT_STATUS_INVALID_PARAMS,
5187 &cp->addr, sizeof(cp->addr));
5188
5189 if (cp->action != 0x00 && cp->action != 0x01)
5190 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5191 MGMT_STATUS_INVALID_PARAMS,
5192 &cp->addr, sizeof(cp->addr));
5193
5194 hci_dev_lock(hdev);
5195
5196 if (cp->addr.type == BDADDR_LE_PUBLIC)
5197 addr_type = ADDR_LE_DEV_PUBLIC;
5198 else
5199 addr_type = ADDR_LE_DEV_RANDOM;
5200
5201 if (cp->action)
5202 auto_conn = HCI_AUTO_CONN_ALWAYS;
5203 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005204 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005205
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005206 /* If the connection parameters don't exist for this device,
5207 * they will be created and configured with defaults.
5208 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005209 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5210 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005211 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5212 MGMT_STATUS_FAILED,
5213 &cp->addr, sizeof(cp->addr));
5214 goto unlock;
5215 }
5216
Marcel Holtmann8afef092014-06-29 22:28:34 +02005217 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5218
Marcel Holtmann2faade52014-06-29 19:44:03 +02005219 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5220 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5221
5222unlock:
5223 hci_dev_unlock(hdev);
5224 return err;
5225}
5226
Marcel Holtmann8afef092014-06-29 22:28:34 +02005227static void device_removed(struct sock *sk, struct hci_dev *hdev,
5228 bdaddr_t *bdaddr, u8 type)
5229{
5230 struct mgmt_ev_device_removed ev;
5231
5232 bacpy(&ev.addr.bdaddr, bdaddr);
5233 ev.addr.type = type;
5234
5235 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5236}
5237
Marcel Holtmann2faade52014-06-29 19:44:03 +02005238static int remove_device(struct sock *sk, struct hci_dev *hdev,
5239 void *data, u16 len)
5240{
5241 struct mgmt_cp_remove_device *cp = data;
5242 int err;
5243
5244 BT_DBG("%s", hdev->name);
5245
5246 hci_dev_lock(hdev);
5247
5248 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005249 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005250 u8 addr_type;
5251
5252 if (!bdaddr_type_is_le(cp->addr.type)) {
5253 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5254 MGMT_STATUS_INVALID_PARAMS,
5255 &cp->addr, sizeof(cp->addr));
5256 goto unlock;
5257 }
5258
5259 if (cp->addr.type == BDADDR_LE_PUBLIC)
5260 addr_type = ADDR_LE_DEV_PUBLIC;
5261 else
5262 addr_type = ADDR_LE_DEV_RANDOM;
5263
Johan Hedbergc71593d2014-07-02 17:37:28 +03005264 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5265 addr_type);
5266 if (!params) {
5267 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5268 MGMT_STATUS_INVALID_PARAMS,
5269 &cp->addr, sizeof(cp->addr));
5270 goto unlock;
5271 }
5272
5273 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5274 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5275 MGMT_STATUS_INVALID_PARAMS,
5276 &cp->addr, sizeof(cp->addr));
5277 goto unlock;
5278 }
5279
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005280 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005281 list_del(&params->list);
5282 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005283 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005284
5285 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005286 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005287 struct hci_conn_params *p, *tmp;
5288
Marcel Holtmann2faade52014-06-29 19:44:03 +02005289 if (cp->addr.type) {
5290 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5291 MGMT_STATUS_INVALID_PARAMS,
5292 &cp->addr, sizeof(cp->addr));
5293 goto unlock;
5294 }
5295
Johan Hedberg19de0822014-07-06 13:06:51 +03005296 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5297 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5298 continue;
5299 device_removed(sk, hdev, &p->addr, p->addr_type);
5300 list_del(&p->action);
5301 list_del(&p->list);
5302 kfree(p);
5303 }
5304
5305 BT_DBG("All LE connection parameters were removed");
5306
5307 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005308 }
5309
5310 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5311 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5312
5313unlock:
5314 hci_dev_unlock(hdev);
5315 return err;
5316}
5317
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005318static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5319 u16 len)
5320{
5321 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005322 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5323 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005324 u16 param_count, expected_len;
5325 int i;
5326
5327 if (!lmp_le_capable(hdev))
5328 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5329 MGMT_STATUS_NOT_SUPPORTED);
5330
5331 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005332 if (param_count > max_param_count) {
5333 BT_ERR("load_conn_param: too big param_count value %u",
5334 param_count);
5335 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5336 MGMT_STATUS_INVALID_PARAMS);
5337 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005338
5339 expected_len = sizeof(*cp) + param_count *
5340 sizeof(struct mgmt_conn_param);
5341 if (expected_len != len) {
5342 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5343 expected_len, len);
5344 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5345 MGMT_STATUS_INVALID_PARAMS);
5346 }
5347
5348 BT_DBG("%s param_count %u", hdev->name, param_count);
5349
5350 hci_dev_lock(hdev);
5351
5352 hci_conn_params_clear_disabled(hdev);
5353
5354 for (i = 0; i < param_count; i++) {
5355 struct mgmt_conn_param *param = &cp->params[i];
5356 struct hci_conn_params *hci_param;
5357 u16 min, max, latency, timeout;
5358 u8 addr_type;
5359
5360 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5361 param->addr.type);
5362
5363 if (param->addr.type == BDADDR_LE_PUBLIC) {
5364 addr_type = ADDR_LE_DEV_PUBLIC;
5365 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5366 addr_type = ADDR_LE_DEV_RANDOM;
5367 } else {
5368 BT_ERR("Ignoring invalid connection parameters");
5369 continue;
5370 }
5371
5372 min = le16_to_cpu(param->min_interval);
5373 max = le16_to_cpu(param->max_interval);
5374 latency = le16_to_cpu(param->latency);
5375 timeout = le16_to_cpu(param->timeout);
5376
5377 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5378 min, max, latency, timeout);
5379
5380 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5381 BT_ERR("Ignoring invalid connection parameters");
5382 continue;
5383 }
5384
5385 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5386 addr_type);
5387 if (!hci_param) {
5388 BT_ERR("Failed to add connection parameters");
5389 continue;
5390 }
5391
5392 hci_param->conn_min_interval = min;
5393 hci_param->conn_max_interval = max;
5394 hci_param->conn_latency = latency;
5395 hci_param->supervision_timeout = timeout;
5396 }
5397
5398 hci_dev_unlock(hdev);
5399
5400 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5401}
5402
Marcel Holtmanndbece372014-07-04 18:11:55 +02005403static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5404 void *data, u16 len)
5405{
5406 struct mgmt_cp_set_external_config *cp = data;
5407 bool changed;
5408 int err;
5409
5410 BT_DBG("%s", hdev->name);
5411
5412 if (hdev_is_powered(hdev))
5413 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5414 MGMT_STATUS_REJECTED);
5415
5416 if (cp->config != 0x00 && cp->config != 0x01)
5417 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5418 MGMT_STATUS_INVALID_PARAMS);
5419
5420 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5421 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5422 MGMT_STATUS_NOT_SUPPORTED);
5423
5424 hci_dev_lock(hdev);
5425
5426 if (cp->config)
5427 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5428 &hdev->dev_flags);
5429 else
5430 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5431 &hdev->dev_flags);
5432
5433 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5434 if (err < 0)
5435 goto unlock;
5436
5437 if (!changed)
5438 goto unlock;
5439
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005440 err = new_options(hdev, sk);
5441
Marcel Holtmanndbece372014-07-04 18:11:55 +02005442 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5443 mgmt_index_removed(hdev);
5444 change_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5445 mgmt_index_added(hdev);
5446 }
5447
5448unlock:
5449 hci_dev_unlock(hdev);
5450 return err;
5451}
5452
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005453static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005454 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5455 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005456 bool var_len;
5457 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005458} mgmt_handlers[] = {
5459 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005460 { read_version, false, MGMT_READ_VERSION_SIZE },
5461 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5462 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5463 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5464 { set_powered, false, MGMT_SETTING_SIZE },
5465 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5466 { set_connectable, false, MGMT_SETTING_SIZE },
5467 { set_fast_connectable, false, MGMT_SETTING_SIZE },
5468 { set_pairable, false, MGMT_SETTING_SIZE },
5469 { set_link_security, false, MGMT_SETTING_SIZE },
5470 { set_ssp, false, MGMT_SETTING_SIZE },
5471 { set_hs, false, MGMT_SETTING_SIZE },
5472 { set_le, false, MGMT_SETTING_SIZE },
5473 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5474 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5475 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5476 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5477 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5478 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5479 { disconnect, false, MGMT_DISCONNECT_SIZE },
5480 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5481 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5482 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5483 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5484 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5485 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5486 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5487 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5488 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5489 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5490 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5491 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005492 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005493 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5494 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5495 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5496 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5497 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5498 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005499 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005500 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005501 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005502 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005503 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005504 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005505 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005506 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005507 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005508 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005509 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005510 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5511 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005512 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5513 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005514 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005515 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005516};
5517
Johan Hedberg03811012010-12-08 00:21:06 +02005518int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5519{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005520 void *buf;
5521 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005522 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005523 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005524 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005525 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005526 int err;
5527
5528 BT_DBG("got %zu bytes", msglen);
5529
5530 if (msglen < sizeof(*hdr))
5531 return -EINVAL;
5532
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005533 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005534 if (!buf)
5535 return -ENOMEM;
5536
5537 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5538 err = -EFAULT;
5539 goto done;
5540 }
5541
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005542 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005543 opcode = __le16_to_cpu(hdr->opcode);
5544 index = __le16_to_cpu(hdr->index);
5545 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005546
5547 if (len != msglen - sizeof(*hdr)) {
5548 err = -EINVAL;
5549 goto done;
5550 }
5551
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005552 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005553 hdev = hci_dev_get(index);
5554 if (!hdev) {
5555 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005556 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005557 goto done;
5558 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005559
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005560 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005561 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005562 err = cmd_status(sk, index, opcode,
5563 MGMT_STATUS_INVALID_INDEX);
5564 goto done;
5565 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005566
5567 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005568 opcode != MGMT_OP_READ_CONFIG_INFO &&
5569 opcode != MGMT_OP_SET_EXTERNAL_CONFIG) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005570 err = cmd_status(sk, index, opcode,
5571 MGMT_STATUS_INVALID_INDEX);
5572 goto done;
5573 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005574 }
5575
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005576 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005577 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005578 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005579 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005580 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005581 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005582 }
5583
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005584 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5585 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5586 err = cmd_status(sk, index, opcode,
5587 MGMT_STATUS_INVALID_INDEX);
5588 goto done;
5589 }
5590
5591 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5592 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005593 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005594 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005595 goto done;
5596 }
5597
Johan Hedbergbe22b542012-03-01 22:24:41 +02005598 handler = &mgmt_handlers[opcode];
5599
5600 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005601 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005602 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005603 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005604 goto done;
5605 }
5606
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005607 if (hdev)
5608 mgmt_init_hdev(sk, hdev);
5609
5610 cp = buf + sizeof(*hdr);
5611
Johan Hedbergbe22b542012-03-01 22:24:41 +02005612 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005613 if (err < 0)
5614 goto done;
5615
Johan Hedberg03811012010-12-08 00:21:06 +02005616 err = msglen;
5617
5618done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005619 if (hdev)
5620 hci_dev_put(hdev);
5621
Johan Hedberg03811012010-12-08 00:21:06 +02005622 kfree(buf);
5623 return err;
5624}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005625
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005626void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005627{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005628 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005629 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005630
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005631 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5632 return;
5633
5634 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5635 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5636 else
5637 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005638}
5639
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005640void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005641{
Johan Hedberg5f159032012-03-02 03:13:19 +02005642 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005643
Marcel Holtmann1514b892013-10-06 08:25:01 -07005644 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005645 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005646
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005647 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5648 return;
5649
Johan Hedberg744cf192011-11-08 20:40:14 +02005650 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005651
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02005652 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5653 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5654 else
5655 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005656}
5657
Andre Guedes6046dc32014-02-26 20:21:51 -03005658/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03005659static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03005660{
5661 struct hci_conn_params *p;
5662
5663 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03005664 /* Needed for AUTO_OFF case where might not "really"
5665 * have been powered off.
5666 */
5667 list_del_init(&p->action);
5668
5669 switch (p->auto_connect) {
5670 case HCI_AUTO_CONN_ALWAYS:
5671 list_add(&p->action, &hdev->pend_le_conns);
5672 break;
5673 case HCI_AUTO_CONN_REPORT:
5674 list_add(&p->action, &hdev->pend_le_reports);
5675 break;
5676 default:
5677 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005678 }
Andre Guedes6046dc32014-02-26 20:21:51 -03005679 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005680
Marcel Holtmannc83ed192014-07-01 19:28:24 +02005681 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005682}
5683
Johan Hedberg229ab392013-03-15 17:06:53 -05005684static void powered_complete(struct hci_dev *hdev, u8 status)
5685{
5686 struct cmd_lookup match = { NULL, hdev };
5687
5688 BT_DBG("status 0x%02x", status);
5689
5690 hci_dev_lock(hdev);
5691
Johan Hedbergd7347f32014-07-04 12:37:23 +03005692 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03005693
Johan Hedberg229ab392013-03-15 17:06:53 -05005694 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5695
5696 new_settings(hdev, match.sk);
5697
5698 hci_dev_unlock(hdev);
5699
5700 if (match.sk)
5701 sock_put(match.sk);
5702}
5703
Johan Hedberg70da6242013-03-15 17:06:51 -05005704static int powered_update_hci(struct hci_dev *hdev)
5705{
Johan Hedberg890ea892013-03-15 17:06:52 -05005706 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05005707 u8 link_sec;
5708
Johan Hedberg890ea892013-03-15 17:06:52 -05005709 hci_req_init(&req, hdev);
5710
Johan Hedberg70da6242013-03-15 17:06:51 -05005711 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
5712 !lmp_host_ssp_capable(hdev)) {
5713 u8 ssp = 1;
5714
Johan Hedberg890ea892013-03-15 17:06:52 -05005715 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005716 }
5717
Johan Hedbergc73eee92013-04-19 18:35:21 +03005718 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
5719 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05005720 struct hci_cp_write_le_host_supported cp;
5721
5722 cp.le = 1;
5723 cp.simul = lmp_le_br_capable(hdev);
5724
5725 /* Check first if we already have the right
5726 * host state (host features set)
5727 */
5728 if (cp.le != lmp_host_le_capable(hdev) ||
5729 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05005730 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
5731 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05005732 }
5733
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005734 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005735 /* Make sure the controller has a good default for
5736 * advertising data. This also applies to the case
5737 * where BR/EDR was toggled during the AUTO_OFF phase.
5738 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005739 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07005740 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07005741 update_scan_rsp_data(&req);
5742 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07005743
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07005744 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
5745 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03005746 }
5747
Johan Hedberg70da6242013-03-15 17:06:51 -05005748 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
5749 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05005750 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
5751 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05005752
5753 if (lmp_bredr_capable(hdev)) {
Johan Hedberg56f87902013-10-02 13:43:13 +03005754 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
5755 set_bredr_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005756 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05005757 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05005758 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05005759 }
5760
Johan Hedberg229ab392013-03-15 17:06:53 -05005761 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05005762}
5763
Johan Hedberg744cf192011-11-08 20:40:14 +02005764int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02005765{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02005766 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05005767 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
5768 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005769 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005770
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005771 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
5772 return 0;
5773
Johan Hedberg5e5282b2012-02-21 16:01:30 +02005774 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05005775 if (powered_update_hci(hdev) == 0)
5776 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02005777
Johan Hedberg229ab392013-03-15 17:06:53 -05005778 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
5779 &match);
5780 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005781 }
5782
Johan Hedberg229ab392013-03-15 17:06:53 -05005783 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
5784 mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
5785
5786 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
5787 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
5788 zero_cod, sizeof(zero_cod), NULL);
5789
5790new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005791 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02005792
5793 if (match.sk)
5794 sock_put(match.sk);
5795
Johan Hedberg7bb895d2012-02-17 01:20:00 +02005796 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02005797}
Johan Hedberg73f22f62010-12-29 16:00:25 +02005798
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005799void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03005800{
5801 struct pending_cmd *cmd;
5802 u8 status;
5803
5804 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
5805 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005806 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03005807
5808 if (err == -ERFKILL)
5809 status = MGMT_STATUS_RFKILLED;
5810 else
5811 status = MGMT_STATUS_FAILED;
5812
Marcel Holtmann3eec7052013-10-06 23:55:46 -07005813 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005814
5815 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03005816}
5817
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005818void mgmt_discoverable_timeout(struct hci_dev *hdev)
5819{
5820 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005821
5822 hci_dev_lock(hdev);
5823
5824 /* When discoverable timeout triggers, then just make sure
5825 * the limited discoverable flag is cleared. Even in the case
5826 * of a timeout triggered from general discoverable, it is
5827 * safe to unconditionally clear the flag.
5828 */
5829 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005830 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005831
5832 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03005833 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
5834 u8 scan = SCAN_PAGE;
5835 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
5836 sizeof(scan), &scan);
5837 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005838 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005839 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005840 hci_req_run(&req, NULL);
5841
5842 hdev->discov_timeout = 0;
5843
Johan Hedberg9a43e252013-10-20 19:00:07 +03005844 new_settings(hdev, NULL);
5845
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07005846 hci_dev_unlock(hdev);
5847}
5848
Marcel Holtmann86a75642013-10-15 06:33:54 -07005849void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
Johan Hedberg73f22f62010-12-29 16:00:25 +02005850{
Marcel Holtmann86a75642013-10-15 06:33:54 -07005851 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02005852
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005853 /* Nothing needed here if there's a pending command since that
5854 * commands request completion callback takes care of everything
5855 * necessary.
5856 */
5857 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
Marcel Holtmann86a75642013-10-15 06:33:54 -07005858 return;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03005859
Johan Hedbergbd107992014-02-24 14:52:19 +02005860 /* Powering off may clear the scan mode - don't let that interfere */
5861 if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5862 return;
5863
Johan Hedberg9a43e252013-10-20 19:00:07 +03005864 if (discoverable) {
Marcel Holtmann86a75642013-10-15 06:33:54 -07005865 changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005866 } else {
5867 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmann86a75642013-10-15 06:33:54 -07005868 changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005869 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005870
Johan Hedberg9a43e252013-10-20 19:00:07 +03005871 if (changed) {
5872 struct hci_request req;
5873
5874 /* In case this change in discoverable was triggered by
5875 * a disabling of connectable there could be a need to
5876 * update the advertising flags.
5877 */
5878 hci_req_init(&req, hdev);
5879 update_adv_data(&req);
5880 hci_req_run(&req, NULL);
5881
Marcel Holtmann86a75642013-10-15 06:33:54 -07005882 new_settings(hdev, NULL);
Johan Hedberg9a43e252013-10-20 19:00:07 +03005883 }
Johan Hedberg73f22f62010-12-29 16:00:25 +02005884}
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005885
Marcel Holtmanna3309162013-10-15 06:33:55 -07005886void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005887{
Marcel Holtmanna3309162013-10-15 06:33:55 -07005888 bool changed;
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005889
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005890 /* Nothing needed here if there's a pending command since that
5891 * commands request completion callback takes care of everything
5892 * necessary.
5893 */
5894 if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
Marcel Holtmanna3309162013-10-15 06:33:55 -07005895 return;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03005896
Johan Hedbergce3f24c2014-02-24 14:52:20 +02005897 /* Powering off may clear the scan mode - don't let that interfere */
5898 if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5899 return;
5900
Marcel Holtmanna3309162013-10-15 06:33:55 -07005901 if (connectable)
5902 changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
5903 else
5904 changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005905
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02005906 if (changed)
Marcel Holtmanna3309162013-10-15 06:33:55 -07005907 new_settings(hdev, NULL);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +02005908}
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005909
Johan Hedberg778b2352014-02-24 14:52:17 +02005910void mgmt_advertising(struct hci_dev *hdev, u8 advertising)
5911{
Johan Hedberg7c4cfab2014-02-24 14:52:21 +02005912 /* Powering off may stop advertising - don't let that interfere */
5913 if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
5914 return;
5915
Johan Hedberg778b2352014-02-24 14:52:17 +02005916 if (advertising)
5917 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
5918 else
5919 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
5920}
5921
Marcel Holtmann4796e8a2013-10-15 06:33:56 -07005922void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005923{
Johan Hedbergca69b792011-11-11 18:10:00 +02005924 u8 mgmt_err = mgmt_status(status);
5925
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005926 if (scan & SCAN_PAGE)
Johan Hedberg744cf192011-11-08 20:40:14 +02005927 mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005928 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005929
5930 if (scan & SCAN_INQUIRY)
Johan Hedberg744cf192011-11-08 20:40:14 +02005931 mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005932 cmd_status_rsp, &mgmt_err);
Johan Hedberg2d7cee52011-11-07 22:16:03 +02005933}
5934
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005935void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
5936 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005937{
Johan Hedberg86742e12011-11-07 23:13:38 +02005938 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005939
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005940 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005941
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005942 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02005943 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03005944 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005945 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03005946 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03005947 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005948
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07005949 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02005950}
Johan Hedbergf7520542011-01-20 12:34:39 +02005951
Johan Hedbergd7b25452014-05-23 13:19:53 +03005952static u8 mgmt_ltk_type(struct smp_ltk *ltk)
5953{
5954 if (ltk->authenticated)
5955 return MGMT_LTK_AUTHENTICATED;
5956
5957 return MGMT_LTK_UNAUTHENTICATED;
5958}
5959
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005960void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005961{
5962 struct mgmt_ev_new_long_term_key ev;
5963
5964 memset(&ev, 0, sizeof(ev));
5965
Marcel Holtmann5192d302014-02-19 17:11:58 -08005966 /* Devices using resolvable or non-resolvable random addresses
5967 * without providing an indentity resolving key don't require
5968 * to store long term keys. Their addresses will change the
5969 * next time around.
5970 *
5971 * Only when a remote device provides an identity address
5972 * make sure the long term key is stored. If the remote
5973 * identity is known, the long term keys are internally
5974 * mapped to the identity address. So allow static random
5975 * and public addresses here.
5976 */
Johan Hedbergba74b662014-02-19 14:57:45 +02005977 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
5978 (key->bdaddr.b[5] & 0xc0) != 0xc0)
5979 ev.store_hint = 0x00;
5980 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07005981 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02005982
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005983 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03005984 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03005985 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005986 ev.key.enc_size = key->enc_size;
5987 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08005988 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005989
Johan Hedberg2ceba532014-06-16 19:25:16 +03005990 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005991 ev.key.master = 1;
5992
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005993 memcpy(ev.key.val, key->val, sizeof(key->val));
5994
Marcel Holtmann083368f2013-10-15 14:26:29 -07005995 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005996}
5997
Johan Hedberg95fbac82014-02-19 15:18:31 +02005998void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
5999{
6000 struct mgmt_ev_new_irk ev;
6001
6002 memset(&ev, 0, sizeof(ev));
6003
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006004 /* For identity resolving keys from devices that are already
6005 * using a public address or static random address, do not
6006 * ask for storing this key. The identity resolving key really
6007 * is only mandatory for devices using resovlable random
6008 * addresses.
6009 *
6010 * Storing all identity resolving keys has the downside that
6011 * they will be also loaded on next boot of they system. More
6012 * identity resolving keys, means more time during scanning is
6013 * needed to actually resolve these addresses.
6014 */
6015 if (bacmp(&irk->rpa, BDADDR_ANY))
6016 ev.store_hint = 0x01;
6017 else
6018 ev.store_hint = 0x00;
6019
Johan Hedberg95fbac82014-02-19 15:18:31 +02006020 bacpy(&ev.rpa, &irk->rpa);
6021 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6022 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6023 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6024
6025 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6026}
6027
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006028void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6029 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006030{
6031 struct mgmt_ev_new_csrk ev;
6032
6033 memset(&ev, 0, sizeof(ev));
6034
6035 /* Devices using resolvable or non-resolvable random addresses
6036 * without providing an indentity resolving key don't require
6037 * to store signature resolving keys. Their addresses will change
6038 * the next time around.
6039 *
6040 * Only when a remote device provides an identity address
6041 * make sure the signature resolving key is stored. So allow
6042 * static random and public addresses here.
6043 */
6044 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6045 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6046 ev.store_hint = 0x00;
6047 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006048 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006049
6050 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6051 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6052 ev.key.master = csrk->master;
6053 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6054
6055 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6056}
6057
Andre Guedesffb5a8272014-07-01 18:10:11 -03006058void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006059 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6060 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006061{
6062 struct mgmt_ev_new_conn_param ev;
6063
Johan Hedbergc103aea2014-07-02 17:37:34 +03006064 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6065 return;
6066
Andre Guedesffb5a8272014-07-01 18:10:11 -03006067 memset(&ev, 0, sizeof(ev));
6068 bacpy(&ev.addr.bdaddr, bdaddr);
6069 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006070 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006071 ev.min_interval = cpu_to_le16(min_interval);
6072 ev.max_interval = cpu_to_le16(max_interval);
6073 ev.latency = cpu_to_le16(latency);
6074 ev.timeout = cpu_to_le16(timeout);
6075
6076 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6077}
6078
Marcel Holtmann94933992013-10-15 10:26:39 -07006079static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6080 u8 data_len)
6081{
6082 eir[eir_len++] = sizeof(type) + data_len;
6083 eir[eir_len++] = type;
6084 memcpy(&eir[eir_len], data, data_len);
6085 eir_len += data_len;
6086
6087 return eir_len;
6088}
6089
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006090void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6091 u8 addr_type, u32 flags, u8 *name, u8 name_len,
6092 u8 *dev_class)
Johan Hedbergf7520542011-01-20 12:34:39 +02006093{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006094 char buf[512];
6095 struct mgmt_ev_device_connected *ev = (void *) buf;
6096 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006097
Johan Hedbergb644ba32012-01-17 21:48:47 +02006098 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006099 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006100
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006101 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006102
Johan Hedbergb644ba32012-01-17 21:48:47 +02006103 if (name_len > 0)
6104 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006105 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006106
6107 if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
Brian Gix53156382012-03-09 14:07:03 -08006108 eir_len = eir_append_data(ev->eir, eir_len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006109 EIR_CLASS_OF_DEV, dev_class, 3);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006110
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006111 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006112
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006113 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6114 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006115}
6116
Johan Hedberg8962ee72011-01-20 12:40:27 +02006117static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6118{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006119 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006120 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006121 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006122
Johan Hedberg88c3df12012-02-09 14:27:38 +02006123 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6124 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006125
Johan Hedbergaee9b212012-02-18 15:07:59 +02006126 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006127 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006128
6129 *sk = cmd->sk;
6130 sock_hold(*sk);
6131
Johan Hedberga664b5b2011-02-19 12:06:02 -03006132 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006133}
6134
Johan Hedberg124f6e32012-02-09 13:50:12 +02006135static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006136{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006137 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006138 struct mgmt_cp_unpair_device *cp = cmd->param;
6139 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006140
6141 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006142 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6143 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006144
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006145 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6146
Johan Hedbergaee9b212012-02-18 15:07:59 +02006147 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006148
6149 mgmt_pending_remove(cmd);
6150}
6151
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006152void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006153 u8 link_type, u8 addr_type, u8 reason,
6154 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006155{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006156 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8b064a32014-02-24 14:52:22 +02006157 struct pending_cmd *power_off;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006158 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006159
Johan Hedberg8b064a32014-02-24 14:52:22 +02006160 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6161 if (power_off) {
6162 struct mgmt_mode *cp = power_off->param;
6163
6164 /* The connection is still in hci_conn_hash so test for 1
6165 * instead of 0 to know if this is the last one.
6166 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006167 if (!cp->val && hci_conn_count(hdev) == 1) {
6168 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006169 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006170 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02006171 }
6172
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006173 if (!mgmt_connected)
6174 return;
6175
Andre Guedes57eb7762013-10-30 19:01:41 -03006176 if (link_type != ACL_LINK && link_type != LE_LINK)
6177 return;
6178
Johan Hedberg744cf192011-11-08 20:40:14 +02006179 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006180
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006181 bacpy(&ev.addr.bdaddr, bdaddr);
6182 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6183 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006184
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006185 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006186
6187 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006188 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006189
Johan Hedberg124f6e32012-02-09 13:50:12 +02006190 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006191 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006192}
6193
Marcel Holtmann78929242013-10-06 23:55:47 -07006194void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6195 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006196{
Andre Guedes3655bba2013-10-30 19:01:40 -03006197 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6198 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006199 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006200 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006201
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006202 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6203 hdev);
6204
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006205 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006206 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006207 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006208
Andre Guedes3655bba2013-10-30 19:01:40 -03006209 cp = cmd->param;
6210
6211 if (bacmp(bdaddr, &cp->addr.bdaddr))
6212 return;
6213
6214 if (cp->addr.type != bdaddr_type)
6215 return;
6216
Johan Hedberg88c3df12012-02-09 14:27:38 +02006217 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006218 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006219
Marcel Holtmann78929242013-10-06 23:55:47 -07006220 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6221 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006222
Johan Hedberga664b5b2011-02-19 12:06:02 -03006223 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006224}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006225
Marcel Holtmann445608d2013-10-06 23:55:48 -07006226void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6227 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006228{
6229 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006230 struct pending_cmd *power_off;
6231
6232 power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6233 if (power_off) {
6234 struct mgmt_mode *cp = power_off->param;
6235
6236 /* The connection is still in hci_conn_hash so test for 1
6237 * instead of 0 to know if this is the last one.
6238 */
Johan Hedberga3172b72014-02-28 09:33:44 +02006239 if (!cp->val && hci_conn_count(hdev) == 1) {
6240 cancel_delayed_work(&hdev->power_off);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006241 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02006242 }
Johan Hedbergc9910d02014-02-27 14:35:12 +02006243 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006244
Johan Hedberg4c659c32011-11-07 23:13:39 +02006245 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006246 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006247 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006248
Marcel Holtmann445608d2013-10-06 23:55:48 -07006249 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006250}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006251
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006252void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006253{
6254 struct mgmt_ev_pin_code_request ev;
6255
Johan Hedbergd8457692012-02-17 14:24:57 +02006256 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006257 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006258 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006259
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006260 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006261}
6262
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006263void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6264 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006265{
6266 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006267 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006268
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006269 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006270 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006271 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006272
Johan Hedbergd8457692012-02-17 14:24:57 +02006273 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006274 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006275
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006276 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6277 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006278
Johan Hedberga664b5b2011-02-19 12:06:02 -03006279 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006280}
6281
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006282void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6283 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006284{
6285 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006286 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006287
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006288 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006289 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006290 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006291
Johan Hedbergd8457692012-02-17 14:24:57 +02006292 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006293 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006294
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006295 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6296 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006297
Johan Hedberga664b5b2011-02-19 12:06:02 -03006298 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006299}
Johan Hedberga5c29682011-02-19 12:05:57 -03006300
Johan Hedberg744cf192011-11-08 20:40:14 +02006301int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006302 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006303 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006304{
6305 struct mgmt_ev_user_confirm_request ev;
6306
Johan Hedberg744cf192011-11-08 20:40:14 +02006307 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006308
Johan Hedberg272d90d2012-02-09 15:26:12 +02006309 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006310 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006311 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006312 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006313
Johan Hedberg744cf192011-11-08 20:40:14 +02006314 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006315 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006316}
6317
Johan Hedberg272d90d2012-02-09 15:26:12 +02006318int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006319 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006320{
6321 struct mgmt_ev_user_passkey_request ev;
6322
6323 BT_DBG("%s", hdev->name);
6324
Johan Hedberg272d90d2012-02-09 15:26:12 +02006325 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006326 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006327
6328 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006329 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006330}
6331
Brian Gix0df4c182011-11-16 13:53:13 -08006332static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006333 u8 link_type, u8 addr_type, u8 status,
6334 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006335{
6336 struct pending_cmd *cmd;
6337 struct mgmt_rp_user_confirm_reply rp;
6338 int err;
6339
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006340 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006341 if (!cmd)
6342 return -ENOENT;
6343
Johan Hedberg272d90d2012-02-09 15:26:12 +02006344 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006345 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006346 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006347 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006348
Johan Hedberga664b5b2011-02-19 12:06:02 -03006349 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006350
6351 return err;
6352}
6353
Johan Hedberg744cf192011-11-08 20:40:14 +02006354int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006355 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006356{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006357 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006358 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006359}
6360
Johan Hedberg272d90d2012-02-09 15:26:12 +02006361int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006362 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006363{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006364 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006365 status,
6366 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006367}
Johan Hedberg2a611692011-02-19 12:06:00 -03006368
Brian Gix604086b2011-11-23 08:28:33 -08006369int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006370 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006371{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006372 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006373 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006374}
6375
Johan Hedberg272d90d2012-02-09 15:26:12 +02006376int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006377 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006378{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006379 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006380 status,
6381 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006382}
6383
Johan Hedberg92a25252012-09-06 18:39:26 +03006384int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6385 u8 link_type, u8 addr_type, u32 passkey,
6386 u8 entered)
6387{
6388 struct mgmt_ev_passkey_notify ev;
6389
6390 BT_DBG("%s", hdev->name);
6391
6392 bacpy(&ev.addr.bdaddr, bdaddr);
6393 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6394 ev.passkey = __cpu_to_le32(passkey);
6395 ev.entered = entered;
6396
6397 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6398}
6399
Marcel Holtmanne5460992013-10-15 14:26:23 -07006400void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6401 u8 addr_type, u8 status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006402{
6403 struct mgmt_ev_auth_failed ev;
6404
Johan Hedbergbab73cb2012-02-09 16:07:29 +02006405 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006406 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006407 ev.status = mgmt_status(status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006408
Marcel Holtmanne5460992013-10-15 14:26:23 -07006409 mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg2a611692011-02-19 12:06:00 -03006410}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006411
Marcel Holtmann464996a2013-10-15 14:26:24 -07006412void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006413{
6414 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006415 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006416
6417 if (status) {
6418 u8 mgmt_err = mgmt_status(status);
6419 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006420 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006421 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006422 }
6423
Marcel Holtmann464996a2013-10-15 14:26:24 -07006424 if (test_bit(HCI_AUTH, &hdev->flags))
6425 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6426 &hdev->dev_flags);
6427 else
6428 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6429 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006430
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006431 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006432 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006433
Johan Hedberg47990ea2012-02-22 11:58:37 +02006434 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006435 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006436
6437 if (match.sk)
6438 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006439}
6440
Johan Hedberg890ea892013-03-15 17:06:52 -05006441static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006442{
Johan Hedberg890ea892013-03-15 17:06:52 -05006443 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006444 struct hci_cp_write_eir cp;
6445
Johan Hedberg976eb202012-10-24 21:12:01 +03006446 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006447 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006448
Johan Hedbergc80da272012-02-22 15:38:48 +02006449 memset(hdev->eir, 0, sizeof(hdev->eir));
6450
Johan Hedbergcacaf522012-02-21 00:52:42 +02006451 memset(&cp, 0, sizeof(cp));
6452
Johan Hedberg890ea892013-03-15 17:06:52 -05006453 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006454}
6455
Marcel Holtmann3e248562013-10-15 14:26:25 -07006456void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006457{
6458 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006459 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006460 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006461
6462 if (status) {
6463 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006464
6465 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006466 &hdev->dev_flags)) {
6467 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006468 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006469 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006470
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006471 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6472 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006473 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006474 }
6475
6476 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006477 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006478 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006479 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6480 if (!changed)
6481 changed = test_and_clear_bit(HCI_HS_ENABLED,
6482 &hdev->dev_flags);
6483 else
6484 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006485 }
6486
6487 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6488
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006489 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006490 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006491
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006492 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006493 sock_put(match.sk);
6494
Johan Hedberg890ea892013-03-15 17:06:52 -05006495 hci_req_init(&req, hdev);
6496
Johan Hedberg37699722014-06-24 14:00:27 +03006497 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6498 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6499 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6500 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006501 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006502 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006503 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006504 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006505
6506 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006507}
6508
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006509void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6510{
6511 struct cmd_lookup match = { NULL, hdev };
6512 bool changed = false;
6513
6514 if (status) {
6515 u8 mgmt_err = mgmt_status(status);
6516
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006517 if (enable) {
6518 if (test_and_clear_bit(HCI_SC_ENABLED,
6519 &hdev->dev_flags))
6520 new_settings(hdev, NULL);
6521 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6522 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006523
6524 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6525 cmd_status_rsp, &mgmt_err);
6526 return;
6527 }
6528
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006529 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006530 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006531 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006532 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006533 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6534 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006535
6536 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6537 settings_rsp, &match);
6538
6539 if (changed)
6540 new_settings(hdev, match.sk);
6541
6542 if (match.sk)
6543 sock_put(match.sk);
6544}
6545
Johan Hedberg92da6092013-03-15 17:06:55 -05006546static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006547{
6548 struct cmd_lookup *match = data;
6549
Johan Hedberg90e70452012-02-23 23:09:40 +02006550 if (match->sk == NULL) {
6551 match->sk = cmd->sk;
6552 sock_hold(match->sk);
6553 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006554}
6555
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006556void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6557 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006558{
Johan Hedberg90e70452012-02-23 23:09:40 +02006559 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006560
Johan Hedberg92da6092013-03-15 17:06:55 -05006561 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6562 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6563 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006564
6565 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006566 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6567 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006568
6569 if (match.sk)
6570 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006571}
6572
Marcel Holtmann7667da32013-10-15 14:26:27 -07006573void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006574{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006575 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006576 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006577
Johan Hedberg13928972013-03-15 17:07:00 -05006578 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006579 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006580
6581 memset(&ev, 0, sizeof(ev));
6582 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006583 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006584
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006585 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006586 if (!cmd) {
6587 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006588
Johan Hedberg13928972013-03-15 17:07:00 -05006589 /* If this is a HCI command related to powering on the
6590 * HCI dev don't send any mgmt signals.
6591 */
6592 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006593 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006594 }
6595
Marcel Holtmann7667da32013-10-15 14:26:27 -07006596 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6597 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006598}
Szymon Jancc35938b2011-03-22 13:12:21 +01006599
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006600void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
6601 u8 *randomizer192, u8 *hash256,
6602 u8 *randomizer256, u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006603{
6604 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006605
Johan Hedberg744cf192011-11-08 20:40:14 +02006606 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006607
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006608 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006609 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006610 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006611
6612 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006613 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6614 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006615 } else {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006616 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
6617 hash256 && randomizer256) {
6618 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006619
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006620 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
6621 memcpy(rp.randomizer192, randomizer192,
6622 sizeof(rp.randomizer192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006623
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006624 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
6625 memcpy(rp.randomizer256, randomizer256,
6626 sizeof(rp.randomizer256));
6627
6628 cmd_complete(cmd->sk, hdev->id,
6629 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6630 &rp, sizeof(rp));
6631 } else {
6632 struct mgmt_rp_read_local_oob_data rp;
6633
6634 memcpy(rp.hash, hash192, sizeof(rp.hash));
6635 memcpy(rp.randomizer, randomizer192,
6636 sizeof(rp.randomizer));
6637
6638 cmd_complete(cmd->sk, hdev->id,
6639 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6640 &rp, sizeof(rp));
6641 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006642 }
6643
6644 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006645}
Johan Hedberge17acd42011-03-30 23:57:16 +03006646
Marcel Holtmann901801b2013-10-06 23:55:51 -07006647void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006648 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6649 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006650{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006651 char buf[512];
6652 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006653 struct smp_irk *irk;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006654 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03006655
Johan Hedberg75ce2082014-07-02 22:42:01 +03006656 /* Don't send events for a non-kernel initiated discovery. With
6657 * LE one exception is if we have pend_le_reports > 0 in which
6658 * case we're doing passive scanning and want these events.
6659 */
6660 if (!hci_discovery_active(hdev)) {
6661 if (link_type == ACL_LINK)
6662 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03006663 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03006664 return;
6665 }
Andre Guedes12602d02013-04-30 15:29:40 -03006666
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006667 /* Make sure that the buffer is big enough. The 5 extra bytes
6668 * are for the potential CoD field.
6669 */
6670 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07006671 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03006672
Johan Hedberg1dc06092012-01-15 21:01:23 +02006673 memset(buf, 0, sizeof(buf));
6674
Johan Hedberg5cedbb82014-02-18 21:41:37 +02006675 irk = hci_get_irk(hdev, bdaddr, addr_type);
6676 if (irk) {
6677 bacpy(&ev->addr.bdaddr, &irk->bdaddr);
6678 ev->addr.type = link_to_bdaddr(link_type, irk->addr_type);
6679 } else {
6680 bacpy(&ev->addr.bdaddr, bdaddr);
6681 ev->addr.type = link_to_bdaddr(link_type, addr_type);
6682 }
6683
Johan Hedberge319d2e2012-01-15 19:51:59 +02006684 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02006685 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03006686
Johan Hedberg1dc06092012-01-15 21:01:23 +02006687 if (eir_len > 0)
Johan Hedberge319d2e2012-01-15 19:51:59 +02006688 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03006689
Johan Hedberg1dc06092012-01-15 21:01:23 +02006690 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
6691 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006692 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02006693
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02006694 if (scan_rsp_len > 0)
6695 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
6696
6697 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
6698 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03006699
Marcel Holtmann901801b2013-10-06 23:55:51 -07006700 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03006701}
Johan Hedberga88a9652011-03-30 13:18:12 +03006702
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006703void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6704 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03006705{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006706 struct mgmt_ev_device_found *ev;
6707 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
6708 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03006709
Johan Hedbergb644ba32012-01-17 21:48:47 +02006710 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03006711
Johan Hedbergb644ba32012-01-17 21:48:47 +02006712 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03006713
Johan Hedbergb644ba32012-01-17 21:48:47 +02006714 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006715 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006716 ev->rssi = rssi;
6717
6718 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006719 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006720
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006721 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006722
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07006723 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03006724}
Johan Hedberg314b2382011-04-27 10:29:57 -04006725
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006726void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04006727{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006728 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02006729 struct pending_cmd *cmd;
6730
Andre Guedes343fb142011-11-22 17:14:19 -03006731 BT_DBG("%s discovering %u", hdev->name, discovering);
6732
Johan Hedberg164a6e72011-11-01 17:06:44 +02006733 if (discovering)
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006734 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006735 else
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006736 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
Johan Hedberg164a6e72011-11-01 17:06:44 +02006737
6738 if (cmd != NULL) {
Johan Hedbergf808e162012-02-19 12:52:07 +02006739 u8 type = hdev->discovery.type;
6740
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006741 cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
6742 sizeof(type));
Johan Hedberg164a6e72011-11-01 17:06:44 +02006743 mgmt_pending_remove(cmd);
6744 }
6745
Johan Hedbergf963e8e2012-02-20 23:30:44 +02006746 memset(&ev, 0, sizeof(ev));
6747 ev.type = hdev->discovery.type;
6748 ev.discovering = discovering;
6749
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07006750 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04006751}
Antti Julku5e762442011-08-25 16:48:02 +03006752
Marcel Holtmann5976e602013-10-06 04:08:14 -07006753static void adv_enable_complete(struct hci_dev *hdev, u8 status)
6754{
6755 BT_DBG("%s status %u", hdev->name, status);
6756
6757 /* Clear the advertising mgmt setting if we failed to re-enable it */
6758 if (status) {
6759 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006760 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006761 }
6762}
6763
6764void mgmt_reenable_advertising(struct hci_dev *hdev)
6765{
6766 struct hci_request req;
6767
Marcel Holtmannb145edc2013-10-10 09:47:54 -07006768 if (hci_conn_num(hdev, LE_LINK) > 0)
Marcel Holtmann5976e602013-10-06 04:08:14 -07006769 return;
6770
6771 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6772 return;
6773
6774 hci_req_init(&req, hdev);
6775 enable_advertising(&req);
6776
6777 /* If this fails we have no option but to let user space know
6778 * that we've disabled advertising.
6779 */
6780 if (hci_req_run(&req, adv_enable_complete) < 0) {
6781 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Marcel Holtmanna6d811e2013-10-06 04:11:12 -07006782 new_settings(hdev, NULL);
Marcel Holtmann5976e602013-10-06 04:08:14 -07006783 }
6784}