blob: 98537b07b720b6259b8ccfa7cd41825d872eacb4 [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 Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
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,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 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,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200138 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300139 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200140 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-12-13 21:07:06 +0200254
Andre Guedes790eff42012-06-07 19:05:46 -0300255 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-12-13 21:07:06 +0200271 kfree_skb(skb);
272
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300273 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200274}
275
Johan Hedbergaee9b2182012-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 Hedbergaee9b2182012-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 Hedbergaee9b2182012-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 Hedbergaee9b2182012-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) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200388 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200389 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200390 continue;
391
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200392 /* Devices marked as raw-only are neither configured
393 * nor unconfigured controllers.
394 */
395 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700396 continue;
397
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200398 if (d->dev_type == HCI_BREDR &&
399 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700400 rp->index[count++] = cpu_to_le16(d->id);
401 BT_DBG("Added hci%u", d->id);
402 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200403 }
404
Johan Hedberg476e44c2012-10-19 20:10:46 +0300405 rp->num_controllers = cpu_to_le16(count);
406 rp_len = sizeof(*rp) + (2 * count);
407
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200408 read_unlock(&hci_dev_list_lock);
409
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200410 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300411 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200412
Johan Hedberga38528f2011-01-22 06:46:43 +0200413 kfree(rp);
414
415 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200416}
417
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200418static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
419 void *data, u16 data_len)
420{
421 struct mgmt_rp_read_unconf_index_list *rp;
422 struct hci_dev *d;
423 size_t rp_len;
424 u16 count;
425 int err;
426
427 BT_DBG("sock %p", sk);
428
429 read_lock(&hci_dev_list_lock);
430
431 count = 0;
432 list_for_each_entry(d, &hci_dev_list, list) {
433 if (d->dev_type == HCI_BREDR &&
434 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
435 count++;
436 }
437
438 rp_len = sizeof(*rp) + (2 * count);
439 rp = kmalloc(rp_len, GFP_ATOMIC);
440 if (!rp) {
441 read_unlock(&hci_dev_list_lock);
442 return -ENOMEM;
443 }
444
445 count = 0;
446 list_for_each_entry(d, &hci_dev_list, list) {
447 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200448 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200449 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
450 continue;
451
452 /* Devices marked as raw-only are neither configured
453 * nor unconfigured controllers.
454 */
455 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
456 continue;
457
458 if (d->dev_type == HCI_BREDR &&
459 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
460 rp->index[count++] = cpu_to_le16(d->id);
461 BT_DBG("Added hci%u", d->id);
462 }
463 }
464
465 rp->num_controllers = cpu_to_le16(count);
466 rp_len = sizeof(*rp) + (2 * count);
467
468 read_unlock(&hci_dev_list_lock);
469
470 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
471 0, rp, rp_len);
472
473 kfree(rp);
474
475 return err;
476}
477
Marcel Holtmanndbece372014-07-04 18:11:55 +0200478static bool is_configured(struct hci_dev *hdev)
479{
480 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
481 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
482 return false;
483
484 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
485 !bacmp(&hdev->public_addr, BDADDR_ANY))
486 return false;
487
488 return true;
489}
490
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200491static __le32 get_missing_options(struct hci_dev *hdev)
492{
493 u32 options = 0;
494
Marcel Holtmanndbece372014-07-04 18:11:55 +0200495 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
496 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200497 options |= MGMT_OPTION_EXTERNAL_CONFIG;
498
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200499 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
500 !bacmp(&hdev->public_addr, BDADDR_ANY))
501 options |= MGMT_OPTION_PUBLIC_ADDRESS;
502
503 return cpu_to_le32(options);
504}
505
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200506static int new_options(struct hci_dev *hdev, struct sock *skip)
507{
508 __le32 options = get_missing_options(hdev);
509
510 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
511 sizeof(options), skip);
512}
513
Marcel Holtmanndbece372014-07-04 18:11:55 +0200514static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
515{
516 __le32 options = get_missing_options(hdev);
517
518 return cmd_complete(sk, hdev->id, opcode, 0, &options,
519 sizeof(options));
520}
521
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200522static int read_config_info(struct sock *sk, struct hci_dev *hdev,
523 void *data, u16 data_len)
524{
525 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200526 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200527
528 BT_DBG("sock %p %s", sk, hdev->name);
529
530 hci_dev_lock(hdev);
531
532 memset(&rp, 0, sizeof(rp));
533 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200534
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200535 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
536 options |= MGMT_OPTION_EXTERNAL_CONFIG;
537
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200538 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200539 options |= MGMT_OPTION_PUBLIC_ADDRESS;
540
541 rp.supported_options = cpu_to_le32(options);
542 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200543
544 hci_dev_unlock(hdev);
545
546 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
547 sizeof(rp));
548}
549
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200550static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200551{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200552 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200553
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200554 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300555 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800556 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300557 settings |= MGMT_SETTING_CONNECTABLE;
558 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200559
Andre Guedesed3fa312012-07-24 15:03:46 -0300560 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500561 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
562 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200563 settings |= MGMT_SETTING_BREDR;
564 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700565
566 if (lmp_ssp_capable(hdev)) {
567 settings |= MGMT_SETTING_SSP;
568 settings |= MGMT_SETTING_HS;
569 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800570
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800571 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200572 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800573 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700574 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100575
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300576 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200577 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300578 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300579 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200580 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300581 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200582
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200583 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
584 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200585 settings |= MGMT_SETTING_CONFIGURATION;
586
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200587 return settings;
588}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200589
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200590static u32 get_current_settings(struct hci_dev *hdev)
591{
592 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200593
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200594 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100595 settings |= MGMT_SETTING_POWERED;
596
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200597 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200598 settings |= MGMT_SETTING_CONNECTABLE;
599
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500600 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
601 settings |= MGMT_SETTING_FAST_CONNECTABLE;
602
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200603 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_DISCOVERABLE;
605
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300606 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300607 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200608
Johan Hedberg56f87902013-10-02 13:43:13 +0300609 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610 settings |= MGMT_SETTING_BREDR;
611
Johan Hedberg06199cf2012-02-22 16:37:11 +0200612 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200613 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200614
Johan Hedberg47990ea2012-02-22 11:58:37 +0200615 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200616 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200617
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200618 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200619 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200620
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200621 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
622 settings |= MGMT_SETTING_HS;
623
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200624 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300625 settings |= MGMT_SETTING_ADVERTISING;
626
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800627 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
628 settings |= MGMT_SETTING_SECURE_CONN;
629
Johan Hedberg0663b292014-06-24 13:15:50 +0300630 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800631 settings |= MGMT_SETTING_DEBUG_KEYS;
632
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200633 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
634 settings |= MGMT_SETTING_PRIVACY;
635
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200636 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200637}
638
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300639#define PNP_INFO_SVCLASS_ID 0x1200
640
Johan Hedberg213202e2013-01-27 00:31:33 +0200641static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
642{
643 u8 *ptr = data, *uuids_start = NULL;
644 struct bt_uuid *uuid;
645
646 if (len < 4)
647 return ptr;
648
649 list_for_each_entry(uuid, &hdev->uuids, list) {
650 u16 uuid16;
651
652 if (uuid->size != 16)
653 continue;
654
655 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
656 if (uuid16 < 0x1100)
657 continue;
658
659 if (uuid16 == PNP_INFO_SVCLASS_ID)
660 continue;
661
662 if (!uuids_start) {
663 uuids_start = ptr;
664 uuids_start[0] = 1;
665 uuids_start[1] = EIR_UUID16_ALL;
666 ptr += 2;
667 }
668
669 /* Stop if not enough space to put next UUID */
670 if ((ptr - data) + sizeof(u16) > len) {
671 uuids_start[1] = EIR_UUID16_SOME;
672 break;
673 }
674
675 *ptr++ = (uuid16 & 0x00ff);
676 *ptr++ = (uuid16 & 0xff00) >> 8;
677 uuids_start[0] += sizeof(uuid16);
678 }
679
680 return ptr;
681}
682
Johan Hedbergcdf19632013-01-27 00:31:34 +0200683static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
684{
685 u8 *ptr = data, *uuids_start = NULL;
686 struct bt_uuid *uuid;
687
688 if (len < 6)
689 return ptr;
690
691 list_for_each_entry(uuid, &hdev->uuids, list) {
692 if (uuid->size != 32)
693 continue;
694
695 if (!uuids_start) {
696 uuids_start = ptr;
697 uuids_start[0] = 1;
698 uuids_start[1] = EIR_UUID32_ALL;
699 ptr += 2;
700 }
701
702 /* Stop if not enough space to put next UUID */
703 if ((ptr - data) + sizeof(u32) > len) {
704 uuids_start[1] = EIR_UUID32_SOME;
705 break;
706 }
707
708 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
709 ptr += sizeof(u32);
710 uuids_start[0] += sizeof(u32);
711 }
712
713 return ptr;
714}
715
Johan Hedbergc00d5752013-01-27 00:31:35 +0200716static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
717{
718 u8 *ptr = data, *uuids_start = NULL;
719 struct bt_uuid *uuid;
720
721 if (len < 18)
722 return ptr;
723
724 list_for_each_entry(uuid, &hdev->uuids, list) {
725 if (uuid->size != 128)
726 continue;
727
728 if (!uuids_start) {
729 uuids_start = ptr;
730 uuids_start[0] = 1;
731 uuids_start[1] = EIR_UUID128_ALL;
732 ptr += 2;
733 }
734
735 /* Stop if not enough space to put next UUID */
736 if ((ptr - data) + 16 > len) {
737 uuids_start[1] = EIR_UUID128_SOME;
738 break;
739 }
740
741 memcpy(ptr, uuid->uuid, 16);
742 ptr += 16;
743 uuids_start[0] += 16;
744 }
745
746 return ptr;
747}
748
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300749static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
750{
751 struct pending_cmd *cmd;
752
753 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
754 if (cmd->opcode == opcode)
755 return cmd;
756 }
757
758 return NULL;
759}
760
Johan Hedberg95868422014-06-28 17:54:07 +0300761static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
762 struct hci_dev *hdev,
763 const void *data)
764{
765 struct pending_cmd *cmd;
766
767 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
768 if (cmd->user_data != data)
769 continue;
770 if (cmd->opcode == opcode)
771 return cmd;
772 }
773
774 return NULL;
775}
776
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700777static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
778{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700779 u8 ad_len = 0;
780 size_t name_len;
781
782 name_len = strlen(hdev->dev_name);
783 if (name_len > 0) {
784 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
785
786 if (name_len > max_len) {
787 name_len = max_len;
788 ptr[1] = EIR_NAME_SHORT;
789 } else
790 ptr[1] = EIR_NAME_COMPLETE;
791
792 ptr[0] = name_len + 1;
793
794 memcpy(ptr + 2, hdev->dev_name, name_len);
795
796 ad_len += (name_len + 2);
797 ptr += (name_len + 2);
798 }
799
800 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700801}
802
803static void update_scan_rsp_data(struct hci_request *req)
804{
805 struct hci_dev *hdev = req->hdev;
806 struct hci_cp_le_set_scan_rsp_data cp;
807 u8 len;
808
Johan Hedberg7751ef12013-10-19 23:38:15 +0300809 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700810 return;
811
812 memset(&cp, 0, sizeof(cp));
813
814 len = create_scan_rsp_data(hdev, cp.data);
815
Johan Hedbergeb438b52013-10-16 15:31:07 +0300816 if (hdev->scan_rsp_data_len == len &&
817 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700818 return;
819
Johan Hedbergeb438b52013-10-16 15:31:07 +0300820 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
821 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700822
823 cp.length = len;
824
825 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
826}
827
Johan Hedberg9a43e252013-10-20 19:00:07 +0300828static u8 get_adv_discov_flags(struct hci_dev *hdev)
829{
830 struct pending_cmd *cmd;
831
832 /* If there's a pending mgmt command the flags will not yet have
833 * their final values, so check for this first.
834 */
835 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
836 if (cmd) {
837 struct mgmt_mode *cp = cmd->param;
838 if (cp->val == 0x01)
839 return LE_AD_GENERAL;
840 else if (cp->val == 0x02)
841 return LE_AD_LIMITED;
842 } else {
843 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
844 return LE_AD_LIMITED;
845 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_GENERAL;
847 }
848
849 return 0;
850}
851
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700852static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700853{
854 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855
Johan Hedberg9a43e252013-10-20 19:00:07 +0300856 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberge8340042014-01-30 11:16:50 -0800858 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860
861 if (flags) {
862 BT_DBG("adv flags 0x%02x", flags);
863
864 ptr[0] = 2;
865 ptr[1] = EIR_FLAGS;
866 ptr[2] = flags;
867
868 ad_len += 3;
869 ptr += 3;
870 }
871
872 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
873 ptr[0] = 2;
874 ptr[1] = EIR_TX_POWER;
875 ptr[2] = (u8) hdev->adv_tx_power;
876
877 ad_len += 3;
878 ptr += 3;
879 }
880
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700881 return ad_len;
882}
883
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700884static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700885{
886 struct hci_dev *hdev = req->hdev;
887 struct hci_cp_le_set_adv_data cp;
888 u8 len;
889
Johan Hedberg10994ce2013-10-19 23:38:16 +0300890 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700891 return;
892
893 memset(&cp, 0, sizeof(cp));
894
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700895 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700896
897 if (hdev->adv_data_len == len &&
898 memcmp(cp.data, hdev->adv_data, len) == 0)
899 return;
900
901 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
902 hdev->adv_data_len = len;
903
904 cp.length = len;
905
906 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
907}
908
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300909int mgmt_update_adv_data(struct hci_dev *hdev)
910{
911 struct hci_request req;
912
913 hci_req_init(&req, hdev);
914 update_adv_data(&req);
915
916 return hci_req_run(&req, NULL);
917}
918
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300919static void create_eir(struct hci_dev *hdev, u8 *data)
920{
921 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300922 size_t name_len;
923
924 name_len = strlen(hdev->dev_name);
925
926 if (name_len > 0) {
927 /* EIR Data type */
928 if (name_len > 48) {
929 name_len = 48;
930 ptr[1] = EIR_NAME_SHORT;
931 } else
932 ptr[1] = EIR_NAME_COMPLETE;
933
934 /* EIR Data length */
935 ptr[0] = name_len + 1;
936
937 memcpy(ptr + 2, hdev->dev_name, name_len);
938
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300939 ptr += (name_len + 2);
940 }
941
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100942 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700943 ptr[0] = 2;
944 ptr[1] = EIR_TX_POWER;
945 ptr[2] = (u8) hdev->inq_tx_power;
946
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700947 ptr += 3;
948 }
949
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700950 if (hdev->devid_source > 0) {
951 ptr[0] = 9;
952 ptr[1] = EIR_DEVICE_ID;
953
954 put_unaligned_le16(hdev->devid_source, ptr + 2);
955 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
956 put_unaligned_le16(hdev->devid_product, ptr + 6);
957 put_unaligned_le16(hdev->devid_version, ptr + 8);
958
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700959 ptr += 10;
960 }
961
Johan Hedberg213202e2013-01-27 00:31:33 +0200962 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200963 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200964 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300965}
966
Johan Hedberg890ea892013-03-15 17:06:52 -0500967static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300968{
Johan Hedberg890ea892013-03-15 17:06:52 -0500969 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970 struct hci_cp_write_eir cp;
971
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200972 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500973 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200974
Johan Hedberg976eb202012-10-24 21:12:01 +0300975 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500976 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300977
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200978 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500979 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200981 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500982 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300983
984 memset(&cp, 0, sizeof(cp));
985
986 create_eir(hdev, cp.data);
987
988 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500989 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300990
991 memcpy(hdev->eir, cp.data, sizeof(cp.data));
992
Johan Hedberg890ea892013-03-15 17:06:52 -0500993 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300994}
995
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200996static u8 get_service_classes(struct hci_dev *hdev)
997{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300998 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200999 u8 val = 0;
1000
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001001 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001002 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003
1004 return val;
1005}
1006
Johan Hedberg890ea892013-03-15 17:06:52 -05001007static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001008{
Johan Hedberg890ea892013-03-15 17:06:52 -05001009 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010 u8 cod[3];
1011
1012 BT_DBG("%s", hdev->name);
1013
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001014 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001015 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001016
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001017 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1018 return;
1019
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001020 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001021 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001022
1023 cod[0] = hdev->minor_class;
1024 cod[1] = hdev->major_class;
1025 cod[2] = get_service_classes(hdev);
1026
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001027 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1028 cod[1] |= 0x20;
1029
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001030 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001031 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032
Johan Hedberg890ea892013-03-15 17:06:52 -05001033 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034}
1035
Johan Hedberga4858cb2014-02-25 19:56:31 +02001036static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001037{
1038 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001039
1040 /* If there's a pending mgmt command the flag will not yet have
1041 * it's final value, so check for this first.
1042 */
1043 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1044 if (cmd) {
1045 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001046 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001047 }
1048
Johan Hedberga4858cb2014-02-25 19:56:31 +02001049 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001050}
1051
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001052static void disable_advertising(struct hci_request *req)
1053{
1054 u8 enable = 0x00;
1055
1056 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1057}
1058
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001059static void enable_advertising(struct hci_request *req)
1060{
1061 struct hci_dev *hdev = req->hdev;
1062 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001063 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001064 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001065
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001066 if (hci_conn_num(hdev, LE_LINK) > 0)
1067 return;
1068
1069 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1070 disable_advertising(req);
1071
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001072 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001073 * hci_update_random_address knows that it's safe to go ahead
1074 * and write a new random address. The flag will be set back on
1075 * as soon as the SET_ADV_ENABLE HCI command completes.
1076 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001077 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001078
Johan Hedberga4858cb2014-02-25 19:56:31 +02001079 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001080
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 /* Set require_privacy to true only when non-connectable
1082 * advertising is used. In that case it is fine to use a
1083 * non-resolvable private address.
1084 */
1085 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001086 return;
1087
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001088 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001089 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1090 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001091 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001092 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001093 cp.channel_map = hdev->le_adv_channel_map;
1094
1095 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1096
1097 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1098}
1099
Johan Hedberg7d785252011-12-15 00:47:39 +02001100static void service_cache_off(struct work_struct *work)
1101{
1102 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001103 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001104 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001105
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001106 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001107 return;
1108
Johan Hedberg890ea892013-03-15 17:06:52 -05001109 hci_req_init(&req, hdev);
1110
Johan Hedberg7d785252011-12-15 00:47:39 +02001111 hci_dev_lock(hdev);
1112
Johan Hedberg890ea892013-03-15 17:06:52 -05001113 update_eir(&req);
1114 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001115
1116 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001117
1118 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001119}
1120
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001121static void rpa_expired(struct work_struct *work)
1122{
1123 struct hci_dev *hdev = container_of(work, struct hci_dev,
1124 rpa_expired.work);
1125 struct hci_request req;
1126
1127 BT_DBG("");
1128
1129 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1130
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001131 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001132 return;
1133
1134 /* The generation of a new RPA and programming it into the
1135 * controller happens in the enable_advertising() function.
1136 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001137 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 hci_req_run(&req, NULL);
1140}
1141
Johan Hedberg6a919082012-02-28 06:17:26 +02001142static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001143{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001144 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001145 return;
1146
Johan Hedberg4f87da82012-03-02 19:55:56 +02001147 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001148 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001149
Johan Hedberg4f87da82012-03-02 19:55:56 +02001150 /* Non-mgmt controlled devices get this bit set
1151 * implicitly so that pairing works for them, however
1152 * for mgmt we require user-space to explicitly enable
1153 * it
1154 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001155 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001156}
1157
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001158static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001159 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001160{
1161 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001162
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001163 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001164
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001165 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Johan Hedberg03811012010-12-08 00:21:06 +02001167 memset(&rp, 0, sizeof(rp));
1168
Johan Hedberg03811012010-12-08 00:21:06 +02001169 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001170
1171 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001172 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001173
1174 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1175 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1176
1177 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001178
1179 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001180 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001181
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001182 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001183
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001184 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001185 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001186}
1187
1188static void mgmt_pending_free(struct pending_cmd *cmd)
1189{
1190 sock_put(cmd->sk);
1191 kfree(cmd->param);
1192 kfree(cmd);
1193}
1194
1195static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001196 struct hci_dev *hdev, void *data,
1197 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001198{
1199 struct pending_cmd *cmd;
1200
Johan Hedbergfca20012014-06-28 17:54:05 +03001201 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001202 if (!cmd)
1203 return NULL;
1204
1205 cmd->opcode = opcode;
1206 cmd->index = hdev->id;
1207
Andre Guedes12b94562012-06-07 19:05:45 -03001208 cmd->param = kmalloc(len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001209 if (!cmd->param) {
1210 kfree(cmd);
1211 return NULL;
1212 }
1213
1214 if (data)
1215 memcpy(cmd->param, data, len);
1216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedberge6fe7982013-10-02 15:45:22 +03001489static u8 mgmt_bredr_support(struct hci_dev *hdev)
1490{
1491 if (!lmp_bredr_capable(hdev))
1492 return MGMT_STATUS_NOT_SUPPORTED;
1493 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1494 return MGMT_STATUS_REJECTED;
1495 else
1496 return MGMT_STATUS_SUCCESS;
1497}
1498
1499static u8 mgmt_le_support(struct hci_dev *hdev)
1500{
1501 if (!lmp_le_capable(hdev))
1502 return MGMT_STATUS_NOT_SUPPORTED;
1503 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1504 return MGMT_STATUS_REJECTED;
1505 else
1506 return MGMT_STATUS_SUCCESS;
1507}
1508
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001509static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1510{
1511 struct pending_cmd *cmd;
1512 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001513 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001514 bool changed;
1515
1516 BT_DBG("status 0x%02x", status);
1517
1518 hci_dev_lock(hdev);
1519
1520 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1521 if (!cmd)
1522 goto unlock;
1523
1524 if (status) {
1525 u8 mgmt_err = mgmt_status(status);
1526 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001527 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001528 goto remove_cmd;
1529 }
1530
1531 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001532 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001533 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1534 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001535
1536 if (hdev->discov_timeout > 0) {
1537 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1538 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1539 to);
1540 }
1541 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001542 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1543 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545
1546 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1547
1548 if (changed)
1549 new_settings(hdev, cmd->sk);
1550
Marcel Holtmann970ba522013-10-15 06:33:57 -07001551 /* When the discoverable mode gets changed, make sure
1552 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001553 * bit correctly set. Also update page scan based on whitelist
1554 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001555 */
1556 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001557 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001558 update_class(&req);
1559 hci_req_run(&req, NULL);
1560
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001561remove_cmd:
1562 mgmt_pending_remove(cmd);
1563
1564unlock:
1565 hci_dev_unlock(hdev);
1566}
1567
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001568static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001569 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001570{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001571 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001572 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001574 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001575 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001576 int err;
1577
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001578 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001579
Johan Hedberg9a43e252013-10-20 19:00:07 +03001580 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1581 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001582 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001583 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001584
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001585 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001586 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1587 MGMT_STATUS_INVALID_PARAMS);
1588
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001589 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001590
1591 /* Disabling discoverable requires that no timeout is set,
1592 * and enabling limited discoverable requires a timeout.
1593 */
1594 if ((cp->val == 0x00 && timeout > 0) ||
1595 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001596 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001597 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001598
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001599 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001600
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001601 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001602 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001603 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001604 goto failed;
1605 }
1606
1607 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001608 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001609 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001610 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001611 goto failed;
1612 }
1613
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001614 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001615 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001616 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001617 goto failed;
1618 }
1619
1620 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001621 bool changed = false;
1622
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001623 /* Setting limited discoverable when powered off is
1624 * not a valid operation since it requires a timeout
1625 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1626 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001627 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1628 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1629 changed = true;
1630 }
1631
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001632 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 if (err < 0)
1634 goto failed;
1635
1636 if (changed)
1637 err = new_settings(hdev, sk);
1638
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001639 goto failed;
1640 }
1641
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001642 /* If the current mode is the same, then just update the timeout
1643 * value with the new value. And if only the timeout gets updated,
1644 * then no need for any HCI transactions.
1645 */
1646 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1647 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1648 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001649 cancel_delayed_work(&hdev->discov_off);
1650 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001651
Marcel Holtmann36261542013-10-15 08:28:51 -07001652 if (cp->val && hdev->discov_timeout > 0) {
1653 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001654 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001655 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001656 }
1657
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001658 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001659 goto failed;
1660 }
1661
1662 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1663 if (!cmd) {
1664 err = -ENOMEM;
1665 goto failed;
1666 }
1667
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001668 /* Cancel any potential discoverable timeout that might be
1669 * still active and store new timeout value. The arming of
1670 * the timeout happens in the complete handler.
1671 */
1672 cancel_delayed_work(&hdev->discov_off);
1673 hdev->discov_timeout = timeout;
1674
Johan Hedbergb456f872013-10-19 23:38:22 +03001675 /* Limited discoverable mode */
1676 if (cp->val == 0x02)
1677 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1678 else
1679 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1680
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001681 hci_req_init(&req, hdev);
1682
Johan Hedberg9a43e252013-10-20 19:00:07 +03001683 /* The procedure for LE-only controllers is much simpler - just
1684 * update the advertising data.
1685 */
1686 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1687 goto update_ad;
1688
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001689 scan = SCAN_PAGE;
1690
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001691 if (cp->val) {
1692 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001693
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001694 if (cp->val == 0x02) {
1695 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001696 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001697 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1698 hci_cp.iac_lap[1] = 0x8b;
1699 hci_cp.iac_lap[2] = 0x9e;
1700 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1701 hci_cp.iac_lap[4] = 0x8b;
1702 hci_cp.iac_lap[5] = 0x9e;
1703 } else {
1704 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001705 hci_cp.num_iac = 1;
1706 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1707 hci_cp.iac_lap[1] = 0x8b;
1708 hci_cp.iac_lap[2] = 0x9e;
1709 }
1710
1711 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1712 (hci_cp.num_iac * 3) + 1, &hci_cp);
1713
1714 scan |= SCAN_INQUIRY;
1715 } else {
1716 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1717 }
1718
1719 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001720
Johan Hedberg9a43e252013-10-20 19:00:07 +03001721update_ad:
1722 update_adv_data(&req);
1723
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001724 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001725 if (err < 0)
1726 mgmt_pending_remove(cmd);
1727
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001728failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001729 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001730 return err;
1731}
1732
Johan Hedberg406d7802013-03-15 17:07:09 -05001733static void write_fast_connectable(struct hci_request *req, bool enable)
1734{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001735 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001736 struct hci_cp_write_page_scan_activity acp;
1737 u8 type;
1738
Johan Hedberg547003b2013-10-21 16:51:53 +03001739 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1740 return;
1741
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001742 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1743 return;
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745 if (enable) {
1746 type = PAGE_SCAN_TYPE_INTERLACED;
1747
1748 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001749 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001750 } else {
1751 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1752
1753 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001754 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001755 }
1756
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001757 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001758
Johan Hedbergbd98b992013-03-15 17:07:13 -05001759 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1760 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1761 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1762 sizeof(acp), &acp);
1763
1764 if (hdev->page_scan_type != type)
1765 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001766}
1767
Johan Hedberg2b76f452013-03-15 17:07:04 -05001768static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1769{
1770 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001771 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001772 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001773
1774 BT_DBG("status 0x%02x", status);
1775
1776 hci_dev_lock(hdev);
1777
1778 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1779 if (!cmd)
1780 goto unlock;
1781
Johan Hedberg37438c12013-10-14 16:20:05 +03001782 if (status) {
1783 u8 mgmt_err = mgmt_status(status);
1784 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1785 goto remove_cmd;
1786 }
1787
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001788 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001789 if (cp->val) {
1790 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1791 &hdev->dev_flags);
1792 discov_changed = false;
1793 } else {
1794 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1795 &hdev->dev_flags);
1796 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1797 &hdev->dev_flags);
1798 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001799
Johan Hedberg2b76f452013-03-15 17:07:04 -05001800 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1801
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001802 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001803 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001804 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001805 if (discov_changed)
1806 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001807 hci_update_background_scan(hdev);
1808 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001809
Johan Hedberg37438c12013-10-14 16:20:05 +03001810remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001811 mgmt_pending_remove(cmd);
1812
1813unlock:
1814 hci_dev_unlock(hdev);
1815}
1816
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001817static int set_connectable_update_settings(struct hci_dev *hdev,
1818 struct sock *sk, u8 val)
1819{
1820 bool changed = false;
1821 int err;
1822
1823 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1824 changed = true;
1825
1826 if (val) {
1827 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1828 } else {
1829 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1830 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1831 }
1832
1833 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1834 if (err < 0)
1835 return err;
1836
Johan Hedberg562064e2014-07-08 16:35:34 +03001837 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001838 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001839 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001840 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001841 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001842
1843 return 0;
1844}
1845
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001846static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001847 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001848{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001849 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001850 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001851 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001852 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001853 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001854
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001855 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001856
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001857 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1858 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001859 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001860 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001861
Johan Hedberga7e80f22013-01-09 16:05:19 +02001862 if (cp->val != 0x00 && cp->val != 0x01)
1863 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1864 MGMT_STATUS_INVALID_PARAMS);
1865
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001866 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001867
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001868 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001869 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001870 goto failed;
1871 }
1872
1873 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001874 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001875 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001876 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001877 goto failed;
1878 }
1879
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001880 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1881 if (!cmd) {
1882 err = -ENOMEM;
1883 goto failed;
1884 }
1885
Johan Hedberg2b76f452013-03-15 17:07:04 -05001886 hci_req_init(&req, hdev);
1887
Johan Hedberg9a43e252013-10-20 19:00:07 +03001888 /* If BR/EDR is not enabled and we disable advertising as a
1889 * by-product of disabling connectable, we need to update the
1890 * advertising flags.
1891 */
1892 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1893 if (!cp->val) {
1894 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1895 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1896 }
1897 update_adv_data(&req);
1898 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001899 if (cp->val) {
1900 scan = SCAN_PAGE;
1901 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001902 /* If we don't have any whitelist entries just
1903 * disable all scanning. If there are entries
1904 * and we had both page and inquiry scanning
1905 * enabled then fall back to only page scanning.
1906 * Otherwise no changes are needed.
1907 */
1908 if (list_empty(&hdev->whitelist))
1909 scan = SCAN_DISABLED;
1910 else if (test_bit(HCI_ISCAN, &hdev->flags))
1911 scan = SCAN_PAGE;
1912 else
1913 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001914
1915 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001916 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001917 cancel_delayed_work(&hdev->discov_off);
1918 }
1919
1920 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1921 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001922
Johan Hedberg3bd27242014-07-28 20:53:58 +03001923no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001924 /* If we're going from non-connectable to connectable or
1925 * vice-versa when fast connectable is enabled ensure that fast
1926 * connectable gets disabled. write_fast_connectable won't do
1927 * anything if the page scan parameters are already what they
1928 * should be.
1929 */
1930 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001931 write_fast_connectable(&req, false);
1932
Johan Hedberge8b12022014-07-10 10:51:27 +03001933 /* Update the advertising parameters if necessary */
1934 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001935 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001936
Johan Hedberg2b76f452013-03-15 17:07:04 -05001937 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001938 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001939 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001940 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001941 err = set_connectable_update_settings(hdev, sk,
1942 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001943 goto failed;
1944 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001945
1946failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001947 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001948 return err;
1949}
1950
Johan Hedbergb2939472014-07-30 09:22:23 +03001951static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001952 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001953{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001954 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001955 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001956 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001958 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001959
Johan Hedberga7e80f22013-01-09 16:05:19 +02001960 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001961 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001962 MGMT_STATUS_INVALID_PARAMS);
1963
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001964 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001965
1966 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001967 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001968 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001969 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001970
Johan Hedbergb2939472014-07-30 09:22:23 +03001971 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001972 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001973 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001974
Marcel Holtmann55594352013-10-06 16:11:57 -07001975 if (changed)
1976 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
Marcel Holtmann55594352013-10-06 16:11:57 -07001978unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001979 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 return err;
1981}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001982
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001983static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1984 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001985{
1986 struct mgmt_mode *cp = data;
1987 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001988 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001989 int err;
1990
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001991 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001992
Johan Hedberge6fe7982013-10-02 15:45:22 +03001993 status = mgmt_bredr_support(hdev);
1994 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03001995 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03001996 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001997
Johan Hedberga7e80f22013-01-09 16:05:19 +02001998 if (cp->val != 0x00 && cp->val != 0x01)
1999 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2000 MGMT_STATUS_INVALID_PARAMS);
2001
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002002 hci_dev_lock(hdev);
2003
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002004 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002005 bool changed = false;
2006
2007 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002008 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002009 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2010 changed = true;
2011 }
2012
2013 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2014 if (err < 0)
2015 goto failed;
2016
2017 if (changed)
2018 err = new_settings(hdev, sk);
2019
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002020 goto failed;
2021 }
2022
2023 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002024 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002025 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002026 goto failed;
2027 }
2028
2029 val = !!cp->val;
2030
2031 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2032 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2033 goto failed;
2034 }
2035
2036 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2037 if (!cmd) {
2038 err = -ENOMEM;
2039 goto failed;
2040 }
2041
2042 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2043 if (err < 0) {
2044 mgmt_pending_remove(cmd);
2045 goto failed;
2046 }
2047
2048failed:
2049 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002050 return err;
2051}
2052
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002053static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002054{
2055 struct mgmt_mode *cp = data;
2056 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002057 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002058 int err;
2059
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002060 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002061
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002062 status = mgmt_bredr_support(hdev);
2063 if (status)
2064 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2065
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002066 if (!lmp_ssp_capable(hdev))
2067 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2068 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002069
Johan Hedberga7e80f22013-01-09 16:05:19 +02002070 if (cp->val != 0x00 && cp->val != 0x01)
2071 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2072 MGMT_STATUS_INVALID_PARAMS);
2073
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002074 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002075
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002076 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002077 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002078
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002079 if (cp->val) {
2080 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2081 &hdev->dev_flags);
2082 } else {
2083 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2084 &hdev->dev_flags);
2085 if (!changed)
2086 changed = test_and_clear_bit(HCI_HS_ENABLED,
2087 &hdev->dev_flags);
2088 else
2089 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090 }
2091
2092 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2093 if (err < 0)
2094 goto failed;
2095
2096 if (changed)
2097 err = new_settings(hdev, sk);
2098
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002099 goto failed;
2100 }
2101
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002102 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2103 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002104 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2105 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002106 goto failed;
2107 }
2108
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002109 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002110 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2111 goto failed;
2112 }
2113
2114 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2115 if (!cmd) {
2116 err = -ENOMEM;
2117 goto failed;
2118 }
2119
Johan Hedberg37699722014-06-24 14:00:27 +03002120 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2121 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2122 sizeof(cp->val), &cp->val);
2123
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002124 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002125 if (err < 0) {
2126 mgmt_pending_remove(cmd);
2127 goto failed;
2128 }
2129
2130failed:
2131 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002132 return err;
2133}
2134
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002135static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002136{
2137 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002138 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002139 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002140 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002141
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002142 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002143
Johan Hedberge6fe7982013-10-02 15:45:22 +03002144 status = mgmt_bredr_support(hdev);
2145 if (status)
2146 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002147
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002148 if (!lmp_ssp_capable(hdev))
2149 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2150 MGMT_STATUS_NOT_SUPPORTED);
2151
2152 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2153 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2154 MGMT_STATUS_REJECTED);
2155
Johan Hedberga7e80f22013-01-09 16:05:19 +02002156 if (cp->val != 0x00 && cp->val != 0x01)
2157 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2158 MGMT_STATUS_INVALID_PARAMS);
2159
Marcel Holtmannee392692013-10-01 22:59:23 -07002160 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002161
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002162 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002163 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002164 } else {
2165 if (hdev_is_powered(hdev)) {
2166 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2167 MGMT_STATUS_REJECTED);
2168 goto unlock;
2169 }
2170
Marcel Holtmannee392692013-10-01 22:59:23 -07002171 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002172 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002173
2174 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2175 if (err < 0)
2176 goto unlock;
2177
2178 if (changed)
2179 err = new_settings(hdev, sk);
2180
2181unlock:
2182 hci_dev_unlock(hdev);
2183 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002184}
2185
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002186static void le_enable_complete(struct hci_dev *hdev, u8 status)
2187{
2188 struct cmd_lookup match = { NULL, hdev };
2189
2190 if (status) {
2191 u8 mgmt_err = mgmt_status(status);
2192
2193 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2194 &mgmt_err);
2195 return;
2196 }
2197
2198 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2199
2200 new_settings(hdev, match.sk);
2201
2202 if (match.sk)
2203 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002204
2205 /* Make sure the controller has a good default for
2206 * advertising data. Restrict the update to when LE
2207 * has actually been enabled. During power on, the
2208 * update in powered_update_hci will take care of it.
2209 */
2210 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2211 struct hci_request req;
2212
2213 hci_dev_lock(hdev);
2214
2215 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002216 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002217 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002218 hci_req_run(&req, NULL);
2219
Johan Hedberga70f4b52014-07-07 15:19:50 +03002220 hci_update_background_scan(hdev);
2221
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002222 hci_dev_unlock(hdev);
2223 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002224}
2225
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002226static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002227{
2228 struct mgmt_mode *cp = data;
2229 struct hci_cp_write_le_host_supported hci_cp;
2230 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002231 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002232 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002233 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002234
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002235 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002236
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002237 if (!lmp_le_capable(hdev))
2238 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2239 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002240
Johan Hedberga7e80f22013-01-09 16:05:19 +02002241 if (cp->val != 0x00 && cp->val != 0x01)
2242 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2243 MGMT_STATUS_INVALID_PARAMS);
2244
Johan Hedbergc73eee92013-04-19 18:35:21 +03002245 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002246 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002247 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2248 MGMT_STATUS_REJECTED);
2249
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002250 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002251
2252 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002253 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002254
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002255 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002256 bool changed = false;
2257
2258 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2259 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2260 changed = true;
2261 }
2262
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002263 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2264 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002265 changed = true;
2266 }
2267
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2269 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002270 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002271
2272 if (changed)
2273 err = new_settings(hdev, sk);
2274
Johan Hedberg1de028c2012-02-29 19:55:35 -08002275 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002276 }
2277
Johan Hedberg4375f102013-09-25 13:26:10 +03002278 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2279 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002280 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002281 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283 }
2284
2285 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2286 if (!cmd) {
2287 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002288 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002289 }
2290
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002291 hci_req_init(&req, hdev);
2292
Johan Hedberg06199cf2012-02-22 16:37:11 +02002293 memset(&hci_cp, 0, sizeof(hci_cp));
2294
2295 if (val) {
2296 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002297 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002298 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002299 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002300 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002303 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2304 &hci_cp);
2305
2306 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302307 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002308 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002309
Johan Hedberg1de028c2012-02-29 19:55:35 -08002310unlock:
2311 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002312 return err;
2313}
2314
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002315/* This is a helper function to test for pending mgmt commands that can
2316 * cause CoD or EIR HCI commands. We can only allow one such pending
2317 * mgmt command at a time since otherwise we cannot easily track what
2318 * the current values are, will be, and based on that calculate if a new
2319 * HCI command needs to be sent and if yes with what value.
2320 */
2321static bool pending_eir_or_class(struct hci_dev *hdev)
2322{
2323 struct pending_cmd *cmd;
2324
2325 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2326 switch (cmd->opcode) {
2327 case MGMT_OP_ADD_UUID:
2328 case MGMT_OP_REMOVE_UUID:
2329 case MGMT_OP_SET_DEV_CLASS:
2330 case MGMT_OP_SET_POWERED:
2331 return true;
2332 }
2333 }
2334
2335 return false;
2336}
2337
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002338static const u8 bluetooth_base_uuid[] = {
2339 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2340 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2341};
2342
2343static u8 get_uuid_size(const u8 *uuid)
2344{
2345 u32 val;
2346
2347 if (memcmp(uuid, bluetooth_base_uuid, 12))
2348 return 128;
2349
2350 val = get_unaligned_le32(&uuid[12]);
2351 if (val > 0xffff)
2352 return 32;
2353
2354 return 16;
2355}
2356
Johan Hedberg92da6092013-03-15 17:06:55 -05002357static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2358{
2359 struct pending_cmd *cmd;
2360
2361 hci_dev_lock(hdev);
2362
2363 cmd = mgmt_pending_find(mgmt_op, hdev);
2364 if (!cmd)
2365 goto unlock;
2366
2367 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2368 hdev->dev_class, 3);
2369
2370 mgmt_pending_remove(cmd);
2371
2372unlock:
2373 hci_dev_unlock(hdev);
2374}
2375
2376static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2377{
2378 BT_DBG("status 0x%02x", status);
2379
2380 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2381}
2382
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002383static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002384{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002385 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002386 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002387 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002388 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002389 int err;
2390
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002391 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002392
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002393 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002394
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002395 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002397 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002398 goto failed;
2399 }
2400
Andre Guedes92c4c202012-06-07 19:05:44 -03002401 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 if (!uuid) {
2403 err = -ENOMEM;
2404 goto failed;
2405 }
2406
2407 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002408 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002409 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002410
Johan Hedbergde66aa62013-01-27 00:31:27 +02002411 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002412
Johan Hedberg890ea892013-03-15 17:06:52 -05002413 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002414
Johan Hedberg890ea892013-03-15 17:06:52 -05002415 update_class(&req);
2416 update_eir(&req);
2417
Johan Hedberg92da6092013-03-15 17:06:55 -05002418 err = hci_req_run(&req, add_uuid_complete);
2419 if (err < 0) {
2420 if (err != -ENODATA)
2421 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002422
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002423 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002424 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002425 goto failed;
2426 }
2427
2428 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002429 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002430 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002431 goto failed;
2432 }
2433
2434 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002435
2436failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002437 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002438 return err;
2439}
2440
Johan Hedberg24b78d02012-02-23 23:24:30 +02002441static bool enable_service_cache(struct hci_dev *hdev)
2442{
2443 if (!hdev_is_powered(hdev))
2444 return false;
2445
2446 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002447 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2448 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002449 return true;
2450 }
2451
2452 return false;
2453}
2454
Johan Hedberg92da6092013-03-15 17:06:55 -05002455static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2456{
2457 BT_DBG("status 0x%02x", status);
2458
2459 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2460}
2461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002462static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002463 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002464{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002465 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002466 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002467 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002468 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 -05002469 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002470 int err, found;
2471
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002472 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002473
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002474 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002475
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002476 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002477 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002478 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002479 goto unlock;
2480 }
2481
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002483 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002484
Johan Hedberg24b78d02012-02-23 23:24:30 +02002485 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002486 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002487 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002488 goto unlock;
2489 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002490
Johan Hedberg9246a862012-02-23 21:33:16 +02002491 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002492 }
2493
2494 found = 0;
2495
Johan Hedberg056341c2013-01-27 00:31:30 +02002496 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002497 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2498 continue;
2499
2500 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002501 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002502 found++;
2503 }
2504
2505 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002506 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002507 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002508 goto unlock;
2509 }
2510
Johan Hedberg9246a862012-02-23 21:33:16 +02002511update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002512 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002513
Johan Hedberg890ea892013-03-15 17:06:52 -05002514 update_class(&req);
2515 update_eir(&req);
2516
Johan Hedberg92da6092013-03-15 17:06:55 -05002517 err = hci_req_run(&req, remove_uuid_complete);
2518 if (err < 0) {
2519 if (err != -ENODATA)
2520 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002521
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002522 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002523 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002524 goto unlock;
2525 }
2526
2527 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002528 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002529 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002530 goto unlock;
2531 }
2532
2533 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002534
2535unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002536 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002537 return err;
2538}
2539
Johan Hedberg92da6092013-03-15 17:06:55 -05002540static void set_class_complete(struct hci_dev *hdev, u8 status)
2541{
2542 BT_DBG("status 0x%02x", status);
2543
2544 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2545}
2546
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002547static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002548 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002549{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002550 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002551 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002552 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002553 int err;
2554
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002555 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002556
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002557 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002558 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2559 MGMT_STATUS_NOT_SUPPORTED);
2560
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002561 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002562
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002563 if (pending_eir_or_class(hdev)) {
2564 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2565 MGMT_STATUS_BUSY);
2566 goto unlock;
2567 }
2568
2569 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2570 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_INVALID_PARAMS);
2572 goto unlock;
2573 }
2574
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002575 hdev->major_class = cp->major;
2576 hdev->minor_class = cp->minor;
2577
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002578 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002579 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002580 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002581 goto unlock;
2582 }
2583
Johan Hedberg890ea892013-03-15 17:06:52 -05002584 hci_req_init(&req, hdev);
2585
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002586 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002587 hci_dev_unlock(hdev);
2588 cancel_delayed_work_sync(&hdev->service_cache);
2589 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002590 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002591 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002592
Johan Hedberg890ea892013-03-15 17:06:52 -05002593 update_class(&req);
2594
Johan Hedberg92da6092013-03-15 17:06:55 -05002595 err = hci_req_run(&req, set_class_complete);
2596 if (err < 0) {
2597 if (err != -ENODATA)
2598 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002599
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002600 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002601 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002602 goto unlock;
2603 }
2604
2605 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002606 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002607 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002608 goto unlock;
2609 }
2610
2611 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002612
Johan Hedbergb5235a62012-02-21 14:32:24 +02002613unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002614 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002615 return err;
2616}
2617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002618static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002619 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002620{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002621 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002622 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2623 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002624 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002625 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002626 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002627
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002628 BT_DBG("request for %s", hdev->name);
2629
2630 if (!lmp_bredr_capable(hdev))
2631 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2632 MGMT_STATUS_NOT_SUPPORTED);
2633
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002634 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002635 if (key_count > max_key_count) {
2636 BT_ERR("load_link_keys: too big key_count value %u",
2637 key_count);
2638 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2639 MGMT_STATUS_INVALID_PARAMS);
2640 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002641
Johan Hedberg86742e12011-11-07 23:13:38 +02002642 expected_len = sizeof(*cp) + key_count *
2643 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002644 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002645 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002646 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002647 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002648 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002649 }
2650
Johan Hedberg4ae14302013-01-20 14:27:13 +02002651 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2652 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2653 MGMT_STATUS_INVALID_PARAMS);
2654
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002655 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002656 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002657
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002658 for (i = 0; i < key_count; i++) {
2659 struct mgmt_link_key_info *key = &cp->keys[i];
2660
Marcel Holtmann8e991132014-01-10 02:07:25 -08002661 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002662 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2663 MGMT_STATUS_INVALID_PARAMS);
2664 }
2665
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002666 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002667
2668 hci_link_keys_clear(hdev);
2669
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002670 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002671 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2672 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002674 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2675 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002676
2677 if (changed)
2678 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002680 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002681 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682
Johan Hedberg58e92932014-06-24 14:00:26 +03002683 /* Always ignore debug keys and require a new pairing if
2684 * the user wants to use them.
2685 */
2686 if (key->type == HCI_LK_DEBUG_COMBINATION)
2687 continue;
2688
Johan Hedberg7652ff62014-06-24 13:15:49 +03002689 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2690 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691 }
2692
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002693 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002694
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002695 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002697 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698}
2699
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002700static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002701 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002702{
2703 struct mgmt_ev_device_unpaired ev;
2704
2705 bacpy(&ev.addr.bdaddr, bdaddr);
2706 ev.addr.type = addr_type;
2707
2708 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002709 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002710}
2711
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002712static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002715 struct mgmt_cp_unpair_device *cp = data;
2716 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002717 struct hci_cp_disconnect dc;
2718 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002719 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002720 int err;
2721
Johan Hedberga8a1d192011-11-10 15:54:38 +02002722 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002723 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2724 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002725
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002726 if (!bdaddr_type_is_valid(cp->addr.type))
2727 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2728 MGMT_STATUS_INVALID_PARAMS,
2729 &rp, sizeof(rp));
2730
Johan Hedberg118da702013-01-20 14:27:20 +02002731 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2732 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2733 MGMT_STATUS_INVALID_PARAMS,
2734 &rp, sizeof(rp));
2735
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002736 hci_dev_lock(hdev);
2737
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002738 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002739 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002740 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002741 goto unlock;
2742 }
2743
Johan Hedberge0b2b272014-02-18 17:14:31 +02002744 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002745 /* If disconnection is requested, then look up the
2746 * connection. If the remote device is connected, it
2747 * will be later used to terminate the link.
2748 *
2749 * Setting it to NULL explicitly will cause no
2750 * termination of the link.
2751 */
2752 if (cp->disconnect)
2753 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2754 &cp->addr.bdaddr);
2755 else
2756 conn = NULL;
2757
Johan Hedberg124f6e32012-02-09 13:50:12 +02002758 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002759 } else {
2760 u8 addr_type;
2761
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002762 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2763 &cp->addr.bdaddr);
2764 if (conn) {
2765 /* Defer clearing up the connection parameters
2766 * until closing to give a chance of keeping
2767 * them if a repairing happens.
2768 */
2769 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2770
2771 /* If disconnection is not requested, then
2772 * clear the connection variable so that the
2773 * link is not terminated.
2774 */
2775 if (!cp->disconnect)
2776 conn = NULL;
2777 }
2778
Johan Hedberge0b2b272014-02-18 17:14:31 +02002779 if (cp->addr.type == BDADDR_LE_PUBLIC)
2780 addr_type = ADDR_LE_DEV_PUBLIC;
2781 else
2782 addr_type = ADDR_LE_DEV_RANDOM;
2783
Johan Hedberga7ec7332014-02-18 17:14:35 +02002784 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2785
Johan Hedberge0b2b272014-02-18 17:14:31 +02002786 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2787 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002788
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002789 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002790 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002791 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002792 goto unlock;
2793 }
2794
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002795 /* If the connection variable is set, then termination of the
2796 * link is requested.
2797 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002798 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002799 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002800 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002801 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002802 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002803 }
2804
Johan Hedberg124f6e32012-02-09 13:50:12 +02002805 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002806 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002807 if (!cmd) {
2808 err = -ENOMEM;
2809 goto unlock;
2810 }
2811
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002812 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002813 dc.reason = 0x13; /* Remote User Terminated Connection */
2814 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2815 if (err < 0)
2816 mgmt_pending_remove(cmd);
2817
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002818unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002819 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002820 return err;
2821}
2822
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002823static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002824 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002825{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002826 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002827 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002828 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002829 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002830 int err;
2831
2832 BT_DBG("");
2833
Johan Hedberg06a63b12013-01-20 14:27:21 +02002834 memset(&rp, 0, sizeof(rp));
2835 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2836 rp.addr.type = cp->addr.type;
2837
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002838 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002839 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2840 MGMT_STATUS_INVALID_PARAMS,
2841 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002842
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002843 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844
2845 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002846 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2847 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002848 goto failed;
2849 }
2850
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002851 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002852 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2853 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002854 goto failed;
2855 }
2856
Andre Guedes591f47f2012-04-24 21:02:49 -03002857 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002858 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2859 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002860 else
2861 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002862
Vishal Agarwalf9607272012-06-13 05:32:43 +05302863 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002864 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2865 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002866 goto failed;
2867 }
2868
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002869 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002870 if (!cmd) {
2871 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002872 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002873 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002874
Johan Hedberge3f2f922014-08-18 20:33:33 +03002875 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002876 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002877 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002878
2879failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002880 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 return err;
2882}
2883
Andre Guedes57c14772012-04-24 21:02:50 -03002884static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002885{
2886 switch (link_type) {
2887 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002888 switch (addr_type) {
2889 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002890 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002891
Johan Hedberg48264f02011-11-09 13:58:58 +02002892 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002893 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002894 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002895 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002896
Johan Hedberg4c659c32011-11-07 23:13:39 +02002897 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002898 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002899 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002900 }
2901}
2902
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002903static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2904 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002905{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002906 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002907 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002908 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002909 int err;
2910 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002911
2912 BT_DBG("");
2913
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002914 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002915
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002916 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002917 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002918 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002919 goto unlock;
2920 }
2921
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002922 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002923 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2924 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002925 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002926 }
2927
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002928 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002929 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002930 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002931 err = -ENOMEM;
2932 goto unlock;
2933 }
2934
Johan Hedberg2784eb42011-01-21 13:56:35 +02002935 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002936 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002937 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2938 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002939 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002940 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002941 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002942 continue;
2943 i++;
2944 }
2945
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002946 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002947
Johan Hedberg4c659c32011-11-07 23:13:39 +02002948 /* Recalculate length in case of filtered SCO connections, etc */
2949 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002950
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002951 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002952 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002953
Johan Hedberga38528f2011-01-22 06:46:43 +02002954 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002955
2956unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002957 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002958 return err;
2959}
2960
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002961static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002962 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002963{
2964 struct pending_cmd *cmd;
2965 int err;
2966
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002967 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002969 if (!cmd)
2970 return -ENOMEM;
2971
Johan Hedbergd8457692012-02-17 14:24:57 +02002972 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002973 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002974 if (err < 0)
2975 mgmt_pending_remove(cmd);
2976
2977 return err;
2978}
2979
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002980static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002981 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002982{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002984 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002985 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002986 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002987 int err;
2988
2989 BT_DBG("");
2990
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002991 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002992
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002993 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002994 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002995 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02002996 goto failed;
2997 }
2998
Johan Hedbergd8457692012-02-17 14:24:57 +02002999 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003000 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003001 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003002 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003003 goto failed;
3004 }
3005
3006 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003007 struct mgmt_cp_pin_code_neg_reply ncp;
3008
3009 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003010
3011 BT_ERR("PIN code is not 16 bytes long");
3012
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003013 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003014 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017
3018 goto failed;
3019 }
3020
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003021 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003022 if (!cmd) {
3023 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003024 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003025 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003026
Johan Hedbergd8457692012-02-17 14:24:57 +02003027 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003028 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003029 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003030
3031 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3032 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003033 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003034
3035failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003036 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003037 return err;
3038}
3039
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003040static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3041 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003042{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003043 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003044
3045 BT_DBG("");
3046
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003047 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3048 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3049 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3050
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003051 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003052
3053 hdev->io_capability = cp->io_capability;
3054
3055 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003056 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003057
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003058 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003059
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3061 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003062}
3063
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003064static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003065{
3066 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003067 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003068
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003069 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003070 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3071 continue;
3072
Johan Hedberge9a416b2011-02-19 12:05:56 -03003073 if (cmd->user_data != conn)
3074 continue;
3075
3076 return cmd;
3077 }
3078
3079 return NULL;
3080}
3081
3082static void pairing_complete(struct pending_cmd *cmd, u8 status)
3083{
3084 struct mgmt_rp_pair_device rp;
3085 struct hci_conn *conn = cmd->user_data;
3086
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003087 bacpy(&rp.addr.bdaddr, &conn->dst);
3088 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003090 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003091 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092
3093 /* So we don't get further callbacks for this connection */
3094 conn->connect_cfm_cb = NULL;
3095 conn->security_cfm_cb = NULL;
3096 conn->disconn_cfm_cb = NULL;
3097
David Herrmann76a68ba2013-04-06 20:28:37 +02003098 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003099 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003100
Johan Hedberga664b5b2011-02-19 12:06:02 -03003101 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003102
3103 /* The device is paired so there is no need to remove
3104 * its connection parameters anymore.
3105 */
3106 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003107}
3108
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003109void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3110{
3111 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3112 struct pending_cmd *cmd;
3113
3114 cmd = find_pairing(conn);
3115 if (cmd)
3116 pairing_complete(cmd, status);
3117}
3118
Johan Hedberge9a416b2011-02-19 12:05:56 -03003119static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3120{
3121 struct pending_cmd *cmd;
3122
3123 BT_DBG("status %u", status);
3124
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003125 cmd = find_pairing(conn);
3126 if (!cmd)
3127 BT_DBG("Unable to find a pending command");
3128 else
Johan Hedberge2113262012-02-18 15:20:03 +02003129 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003130}
3131
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003132static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303133{
3134 struct pending_cmd *cmd;
3135
3136 BT_DBG("status %u", status);
3137
3138 if (!status)
3139 return;
3140
3141 cmd = find_pairing(conn);
3142 if (!cmd)
3143 BT_DBG("Unable to find a pending command");
3144 else
3145 pairing_complete(cmd, mgmt_status(status));
3146}
3147
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003148static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003149 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003150{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003151 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003152 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003153 struct pending_cmd *cmd;
3154 u8 sec_level, auth_type;
3155 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003156 int err;
3157
3158 BT_DBG("");
3159
Szymon Jancf950a30e2013-01-18 12:48:07 +01003160 memset(&rp, 0, sizeof(rp));
3161 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3162 rp.addr.type = cp->addr.type;
3163
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003164 if (!bdaddr_type_is_valid(cp->addr.type))
3165 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3166 MGMT_STATUS_INVALID_PARAMS,
3167 &rp, sizeof(rp));
3168
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003169 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3170 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3171 MGMT_STATUS_INVALID_PARAMS,
3172 &rp, sizeof(rp));
3173
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003174 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003175
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003176 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003177 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3178 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003179 goto unlock;
3180 }
3181
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003182 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003183 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003184
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003185 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003186 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3187 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003188 } else {
3189 u8 addr_type;
3190
3191 /* Convert from L2CAP channel address type to HCI address type
3192 */
3193 if (cp->addr.type == BDADDR_LE_PUBLIC)
3194 addr_type = ADDR_LE_DEV_PUBLIC;
3195 else
3196 addr_type = ADDR_LE_DEV_RANDOM;
3197
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003198 /* When pairing a new device, it is expected to remember
3199 * this device for future connections. Adding the connection
3200 * parameter information ahead of time allows tracking
3201 * of the slave preferred values and will speed up any
3202 * further connection establishment.
3203 *
3204 * If connection parameters already exist, then they
3205 * will be kept and this function does nothing.
3206 */
3207 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3208
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003209 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003210 sec_level, HCI_LE_CONN_TIMEOUT,
3211 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003212 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003213
Ville Tervo30e76272011-02-22 16:10:53 -03003214 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003215 int status;
3216
3217 if (PTR_ERR(conn) == -EBUSY)
3218 status = MGMT_STATUS_BUSY;
3219 else
3220 status = MGMT_STATUS_CONNECT_FAILED;
3221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003222 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003223 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003224 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003225 goto unlock;
3226 }
3227
3228 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003229 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003230 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003231 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003232 goto unlock;
3233 }
3234
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003235 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003236 if (!cmd) {
3237 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003238 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003239 goto unlock;
3240 }
3241
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003242 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003243 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003244 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003245 conn->security_cfm_cb = pairing_complete_cb;
3246 conn->disconn_cfm_cb = pairing_complete_cb;
3247 } else {
3248 conn->connect_cfm_cb = le_pairing_complete_cb;
3249 conn->security_cfm_cb = le_pairing_complete_cb;
3250 conn->disconn_cfm_cb = le_pairing_complete_cb;
3251 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003252
Johan Hedberge9a416b2011-02-19 12:05:56 -03003253 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003254 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003255
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003256 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003257 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003258 pairing_complete(cmd, 0);
3259
3260 err = 0;
3261
3262unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003263 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003264 return err;
3265}
3266
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003267static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3268 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003269{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003270 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003271 struct pending_cmd *cmd;
3272 struct hci_conn *conn;
3273 int err;
3274
3275 BT_DBG("");
3276
Johan Hedberg28424702012-02-02 04:02:29 +02003277 hci_dev_lock(hdev);
3278
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003279 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003280 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003281 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003282 goto unlock;
3283 }
3284
Johan Hedberg28424702012-02-02 04:02:29 +02003285 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3286 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003287 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003288 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003289 goto unlock;
3290 }
3291
3292 conn = cmd->user_data;
3293
3294 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003295 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003297 goto unlock;
3298 }
3299
3300 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3301
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003302 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003303 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003304unlock:
3305 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003306 return err;
3307}
3308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003309static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003310 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003312{
Johan Hedberga5c29682011-02-19 12:05:57 -03003313 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003314 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003315 int err;
3316
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003317 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003318
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003319 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003320 err = cmd_complete(sk, hdev->id, mgmt_op,
3321 MGMT_STATUS_NOT_POWERED, addr,
3322 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003323 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003324 }
3325
Johan Hedberg1707c602013-03-15 17:07:15 -05003326 if (addr->type == BDADDR_BREDR)
3327 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003328 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003329 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003330
Johan Hedberg272d90d2012-02-09 15:26:12 +02003331 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003332 err = cmd_complete(sk, hdev->id, mgmt_op,
3333 MGMT_STATUS_NOT_CONNECTED, addr,
3334 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003335 goto done;
3336 }
3337
Johan Hedberg1707c602013-03-15 17:07:15 -05003338 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003339 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003340 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003341 err = cmd_complete(sk, hdev->id, mgmt_op,
3342 MGMT_STATUS_SUCCESS, addr,
3343 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003344 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003345 err = cmd_complete(sk, hdev->id, mgmt_op,
3346 MGMT_STATUS_FAILED, addr,
3347 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003348
Brian Gix47c15e22011-11-16 13:53:14 -08003349 goto done;
3350 }
3351
Johan Hedberg1707c602013-03-15 17:07:15 -05003352 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003353 if (!cmd) {
3354 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003355 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003356 }
3357
Brian Gix0df4c182011-11-16 13:53:13 -08003358 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003359 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3360 struct hci_cp_user_passkey_reply cp;
3361
Johan Hedberg1707c602013-03-15 17:07:15 -05003362 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003363 cp.passkey = passkey;
3364 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3365 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003366 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3367 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003368
Johan Hedberga664b5b2011-02-19 12:06:02 -03003369 if (err < 0)
3370 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003371
Brian Gix0df4c182011-11-16 13:53:13 -08003372done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003373 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003374 return err;
3375}
3376
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303377static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3378 void *data, u16 len)
3379{
3380 struct mgmt_cp_pin_code_neg_reply *cp = data;
3381
3382 BT_DBG("");
3383
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303385 MGMT_OP_PIN_CODE_NEG_REPLY,
3386 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3387}
3388
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003389static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3390 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003391{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003392 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003393
3394 BT_DBG("");
3395
3396 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003397 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003398 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003399
Johan Hedberg1707c602013-03-15 17:07:15 -05003400 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003401 MGMT_OP_USER_CONFIRM_REPLY,
3402 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003403}
3404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003405static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003406 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003407{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003408 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003409
3410 BT_DBG("");
3411
Johan Hedberg1707c602013-03-15 17:07:15 -05003412 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003413 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3414 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003415}
3416
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003417static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3418 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003419{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003420 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003421
3422 BT_DBG("");
3423
Johan Hedberg1707c602013-03-15 17:07:15 -05003424 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003425 MGMT_OP_USER_PASSKEY_REPLY,
3426 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003427}
3428
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003429static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003430 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003431{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003432 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003433
3434 BT_DBG("");
3435
Johan Hedberg1707c602013-03-15 17:07:15 -05003436 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003437 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3438 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003439}
3440
Johan Hedberg13928972013-03-15 17:07:00 -05003441static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003442{
Johan Hedberg13928972013-03-15 17:07:00 -05003443 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003444 struct hci_cp_write_local_name cp;
3445
Johan Hedberg13928972013-03-15 17:07:00 -05003446 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003447
Johan Hedberg890ea892013-03-15 17:06:52 -05003448 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003449}
3450
Johan Hedberg13928972013-03-15 17:07:00 -05003451static void set_name_complete(struct hci_dev *hdev, u8 status)
3452{
3453 struct mgmt_cp_set_local_name *cp;
3454 struct pending_cmd *cmd;
3455
3456 BT_DBG("status 0x%02x", status);
3457
3458 hci_dev_lock(hdev);
3459
3460 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3461 if (!cmd)
3462 goto unlock;
3463
3464 cp = cmd->param;
3465
3466 if (status)
3467 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3468 mgmt_status(status));
3469 else
3470 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3471 cp, sizeof(*cp));
3472
3473 mgmt_pending_remove(cmd);
3474
3475unlock:
3476 hci_dev_unlock(hdev);
3477}
3478
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003479static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003480 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003481{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003482 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003483 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003484 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003485 int err;
3486
3487 BT_DBG("");
3488
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003489 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003490
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003491 /* If the old values are the same as the new ones just return a
3492 * direct command complete event.
3493 */
3494 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3495 !memcmp(hdev->short_name, cp->short_name,
3496 sizeof(hdev->short_name))) {
3497 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3498 data, len);
3499 goto failed;
3500 }
3501
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003502 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003503
Johan Hedbergb5235a62012-02-21 14:32:24 +02003504 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003505 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003506
3507 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003508 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003509 if (err < 0)
3510 goto failed;
3511
3512 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003513 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003514
Johan Hedbergb5235a62012-02-21 14:32:24 +02003515 goto failed;
3516 }
3517
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003518 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003519 if (!cmd) {
3520 err = -ENOMEM;
3521 goto failed;
3522 }
3523
Johan Hedberg13928972013-03-15 17:07:00 -05003524 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3525
Johan Hedberg890ea892013-03-15 17:06:52 -05003526 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003527
3528 if (lmp_bredr_capable(hdev)) {
3529 update_name(&req);
3530 update_eir(&req);
3531 }
3532
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003533 /* The name is stored in the scan response data and so
3534 * no need to udpate the advertising data here.
3535 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003536 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003537 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003538
Johan Hedberg13928972013-03-15 17:07:00 -05003539 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003540 if (err < 0)
3541 mgmt_pending_remove(cmd);
3542
3543failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003544 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003545 return err;
3546}
3547
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003548static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003549 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003550{
Szymon Jancc35938b2011-03-22 13:12:21 +01003551 struct pending_cmd *cmd;
3552 int err;
3553
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003554 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003555
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003556 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003557
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003558 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003559 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003560 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003561 goto unlock;
3562 }
3563
Andre Guedes9a1a1992012-07-24 15:03:48 -03003564 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003565 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003566 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003567 goto unlock;
3568 }
3569
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003570 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003571 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003572 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003573 goto unlock;
3574 }
3575
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003576 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003577 if (!cmd) {
3578 err = -ENOMEM;
3579 goto unlock;
3580 }
3581
Johan Hedberg710f11c2014-05-26 11:21:22 +03003582 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003583 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3584 0, NULL);
3585 else
3586 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3587
Szymon Jancc35938b2011-03-22 13:12:21 +01003588 if (err < 0)
3589 mgmt_pending_remove(cmd);
3590
3591unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003592 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003593 return err;
3594}
3595
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003596static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003597 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003598{
Szymon Janc2763eda2011-03-22 13:12:22 +01003599 int err;
3600
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003601 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003602
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003603 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003604
Marcel Holtmannec109112014-01-10 02:07:30 -08003605 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3606 struct mgmt_cp_add_remote_oob_data *cp = data;
3607 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003608
Johan Hedbergc19a4952014-11-17 20:52:19 +02003609 if (cp->addr.type != BDADDR_BREDR) {
3610 err = cmd_complete(sk, hdev->id,
3611 MGMT_OP_ADD_REMOTE_OOB_DATA,
3612 MGMT_STATUS_INVALID_PARAMS,
3613 &cp->addr, sizeof(cp->addr));
3614 goto unlock;
3615 }
3616
Marcel Holtmannec109112014-01-10 02:07:30 -08003617 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003618 cp->addr.type, cp->hash,
3619 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003620 if (err < 0)
3621 status = MGMT_STATUS_FAILED;
3622 else
3623 status = MGMT_STATUS_SUCCESS;
3624
3625 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3626 status, &cp->addr, sizeof(cp->addr));
3627 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3628 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003629 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003630 u8 status;
3631
Johan Hedbergc19a4952014-11-17 20:52:19 +02003632 if (cp->addr.type != BDADDR_BREDR) {
3633 err = cmd_complete(sk, hdev->id,
3634 MGMT_OP_ADD_REMOTE_OOB_DATA,
3635 MGMT_STATUS_INVALID_PARAMS,
3636 &cp->addr, sizeof(cp->addr));
3637 goto unlock;
3638 }
3639
Johan Hedberg86df9202014-10-26 20:52:27 +01003640 if (bdaddr_type_is_le(cp->addr.type)) {
3641 rand192 = NULL;
3642 hash192 = NULL;
3643 } else {
3644 rand192 = cp->rand192;
3645 hash192 = cp->hash192;
3646 }
3647
Johan Hedberg81328d52014-10-26 20:33:47 +01003648 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003649 cp->addr.type, hash192, rand192,
3650 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003651 if (err < 0)
3652 status = MGMT_STATUS_FAILED;
3653 else
3654 status = MGMT_STATUS_SUCCESS;
3655
3656 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3657 status, &cp->addr, sizeof(cp->addr));
3658 } else {
3659 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3660 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3661 MGMT_STATUS_INVALID_PARAMS);
3662 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003663
Johan Hedbergc19a4952014-11-17 20:52:19 +02003664unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003665 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003666 return err;
3667}
3668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003669static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003670 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003671{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003672 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003673 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003674 int err;
3675
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003676 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003677
Johan Hedbergc19a4952014-11-17 20:52:19 +02003678 if (cp->addr.type != BDADDR_BREDR)
3679 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3680 MGMT_STATUS_INVALID_PARAMS,
3681 &cp->addr, sizeof(cp->addr));
3682
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003683 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003684
Johan Hedbergeedbd582014-11-15 09:34:23 +02003685 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3686 hci_remote_oob_data_clear(hdev);
3687 status = MGMT_STATUS_SUCCESS;
3688 goto done;
3689 }
3690
Johan Hedberg6928a922014-10-26 20:46:09 +01003691 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003692 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003693 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003694 else
Szymon Janca6785be2012-12-13 15:11:21 +01003695 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003696
Johan Hedbergeedbd582014-11-15 09:34:23 +02003697done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003698 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003699 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003700
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003701 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003702 return err;
3703}
3704
Marcel Holtmann80190442014-12-04 11:36:36 +01003705static bool trigger_discovery(struct hci_request *req, u8 *status)
3706{
3707 struct hci_dev *hdev = req->hdev;
3708 struct hci_cp_le_set_scan_param param_cp;
3709 struct hci_cp_le_set_scan_enable enable_cp;
3710 struct hci_cp_inquiry inq_cp;
3711 /* General inquiry access code (GIAC) */
3712 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3713 u8 own_addr_type;
3714 int err;
3715
3716 switch (hdev->discovery.type) {
3717 case DISCOV_TYPE_BREDR:
3718 *status = mgmt_bredr_support(hdev);
3719 if (*status)
3720 return false;
3721
3722 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3723 *status = MGMT_STATUS_BUSY;
3724 return false;
3725 }
3726
3727 hci_inquiry_cache_flush(hdev);
3728
3729 memset(&inq_cp, 0, sizeof(inq_cp));
3730 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3731 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3732 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3733 break;
3734
3735 case DISCOV_TYPE_LE:
3736 case DISCOV_TYPE_INTERLEAVED:
3737 *status = mgmt_le_support(hdev);
3738 if (*status)
3739 return false;
3740
3741 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3742 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3743 *status = MGMT_STATUS_NOT_SUPPORTED;
3744 return false;
3745 }
3746
3747 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3748 /* Don't let discovery abort an outgoing
3749 * connection attempt that's using directed
3750 * advertising.
3751 */
3752 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3753 BT_CONNECT)) {
3754 *status = MGMT_STATUS_REJECTED;
3755 return false;
3756 }
3757
3758 disable_advertising(req);
3759 }
3760
3761 /* If controller is scanning, it means the background scanning
3762 * is running. Thus, we should temporarily stop it in order to
3763 * set the discovery scanning parameters.
3764 */
3765 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3766 hci_req_add_le_scan_disable(req);
3767
3768 memset(&param_cp, 0, sizeof(param_cp));
3769
3770 /* All active scans will be done with either a resolvable
3771 * private address (when privacy feature has been enabled)
3772 * or unresolvable private address.
3773 */
3774 err = hci_update_random_address(req, true, &own_addr_type);
3775 if (err < 0) {
3776 *status = MGMT_STATUS_FAILED;
3777 return false;
3778 }
3779
3780 param_cp.type = LE_SCAN_ACTIVE;
3781 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3782 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3783 param_cp.own_address_type = own_addr_type;
3784 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3785 &param_cp);
3786
3787 memset(&enable_cp, 0, sizeof(enable_cp));
3788 enable_cp.enable = LE_SCAN_ENABLE;
3789 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3790 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3791 &enable_cp);
3792 break;
3793
3794 default:
3795 *status = MGMT_STATUS_INVALID_PARAMS;
3796 return false;
3797 }
3798
3799 return true;
3800}
3801
Andre Guedes7c307722013-04-30 15:29:28 -03003802static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3803{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003804 struct pending_cmd *cmd;
3805 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003806
Andre Guedes7c307722013-04-30 15:29:28 -03003807 BT_DBG("status %d", status);
3808
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003809 hci_dev_lock(hdev);
3810
3811 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003812 if (!cmd)
3813 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3814
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003815 if (cmd) {
3816 u8 type = hdev->discovery.type;
3817
3818 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
3819 mgmt_status(status), &type, sizeof(type));
3820 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003821 }
3822
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003823 if (status) {
3824 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3825 goto unlock;
3826 }
3827
Andre Guedes7c307722013-04-30 15:29:28 -03003828 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003829
3830 switch (hdev->discovery.type) {
3831 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003832 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003833 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003834 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003835 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003836 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003837 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003838 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003839 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003840 default:
3841 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003842 timeout = 0;
3843 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003844 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003845
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003846 if (timeout)
3847 queue_delayed_work(hdev->workqueue,
3848 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003849
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003850unlock:
3851 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003852}
3853
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003854static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003855 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003856{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003857 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003858 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003859 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003860 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003861 int err;
3862
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003863 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003864
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003865 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003866
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003867 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003868 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3869 MGMT_STATUS_NOT_POWERED,
3870 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003871 goto failed;
3872 }
3873
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003874 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3875 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003876 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3877 MGMT_STATUS_BUSY, &cp->type,
3878 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003879 goto failed;
3880 }
3881
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003882 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003883 if (!cmd) {
3884 err = -ENOMEM;
3885 goto failed;
3886 }
3887
Marcel Holtmann22078802014-12-05 11:45:22 +01003888 /* Clear the discovery filter first to free any previously
3889 * allocated memory for the UUID list.
3890 */
3891 hci_discovery_filter_clear(hdev);
3892
Andre Guedes4aab14e2012-02-17 20:39:36 -03003893 hdev->discovery.type = cp->type;
3894
Andre Guedes7c307722013-04-30 15:29:28 -03003895 hci_req_init(&req, hdev);
3896
Marcel Holtmann80190442014-12-04 11:36:36 +01003897 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003898 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003899 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003900 mgmt_pending_remove(cmd);
3901 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003902 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003903
Andre Guedes7c307722013-04-30 15:29:28 -03003904 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003905 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003906 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003907 goto failed;
3908 }
3909
3910 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003911
3912failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003913 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003914 return err;
3915}
3916
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003917static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3918 void *data, u16 len)
3919{
3920 struct mgmt_cp_start_service_discovery *cp = data;
3921 struct pending_cmd *cmd;
3922 struct hci_request req;
3923 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3924 u16 uuid_count, expected_len;
3925 u8 status;
3926 int err;
3927
3928 BT_DBG("%s", hdev->name);
3929
3930 hci_dev_lock(hdev);
3931
3932 if (!hdev_is_powered(hdev)) {
3933 err = cmd_complete(sk, hdev->id,
3934 MGMT_OP_START_SERVICE_DISCOVERY,
3935 MGMT_STATUS_NOT_POWERED,
3936 &cp->type, sizeof(cp->type));
3937 goto failed;
3938 }
3939
3940 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3941 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3942 err = cmd_complete(sk, hdev->id,
3943 MGMT_OP_START_SERVICE_DISCOVERY,
3944 MGMT_STATUS_BUSY, &cp->type,
3945 sizeof(cp->type));
3946 goto failed;
3947 }
3948
3949 uuid_count = __le16_to_cpu(cp->uuid_count);
3950 if (uuid_count > max_uuid_count) {
3951 BT_ERR("service_discovery: too big uuid_count value %u",
3952 uuid_count);
3953 err = cmd_complete(sk, hdev->id,
3954 MGMT_OP_START_SERVICE_DISCOVERY,
3955 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3956 sizeof(cp->type));
3957 goto failed;
3958 }
3959
3960 expected_len = sizeof(*cp) + uuid_count * 16;
3961 if (expected_len != len) {
3962 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3963 expected_len, len);
3964 err = cmd_complete(sk, hdev->id,
3965 MGMT_OP_START_SERVICE_DISCOVERY,
3966 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3967 sizeof(cp->type));
3968 goto failed;
3969 }
3970
3971 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
3972 hdev, NULL, 0);
3973 if (!cmd) {
3974 err = -ENOMEM;
3975 goto failed;
3976 }
3977
Marcel Holtmann22078802014-12-05 11:45:22 +01003978 /* Clear the discovery filter first to free any previously
3979 * allocated memory for the UUID list.
3980 */
3981 hci_discovery_filter_clear(hdev);
3982
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003983 hdev->discovery.type = cp->type;
3984 hdev->discovery.rssi = cp->rssi;
3985 hdev->discovery.uuid_count = uuid_count;
3986
3987 if (uuid_count > 0) {
3988 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
3989 GFP_KERNEL);
3990 if (!hdev->discovery.uuids) {
3991 err = cmd_complete(sk, hdev->id,
3992 MGMT_OP_START_SERVICE_DISCOVERY,
3993 MGMT_STATUS_FAILED,
3994 &cp->type, sizeof(cp->type));
3995 mgmt_pending_remove(cmd);
3996 goto failed;
3997 }
3998 }
3999
4000 hci_req_init(&req, hdev);
4001
4002 if (!trigger_discovery(&req, &status)) {
4003 err = cmd_complete(sk, hdev->id,
4004 MGMT_OP_START_SERVICE_DISCOVERY,
4005 status, &cp->type, sizeof(cp->type));
4006 mgmt_pending_remove(cmd);
4007 goto failed;
4008 }
4009
4010 err = hci_req_run(&req, start_discovery_complete);
4011 if (err < 0) {
4012 mgmt_pending_remove(cmd);
4013 goto failed;
4014 }
4015
4016 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4017
4018failed:
4019 hci_dev_unlock(hdev);
4020 return err;
4021}
4022
Andre Guedes0e05bba2013-04-30 15:29:33 -03004023static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4024{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004025 struct pending_cmd *cmd;
4026
Andre Guedes0e05bba2013-04-30 15:29:33 -03004027 BT_DBG("status %d", status);
4028
4029 hci_dev_lock(hdev);
4030
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004031 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4032 if (cmd) {
4033 u8 type = hdev->discovery.type;
4034
4035 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
4036 mgmt_status(status), &type, sizeof(type));
4037 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004038 }
4039
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004040 if (!status)
4041 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004042
Andre Guedes0e05bba2013-04-30 15:29:33 -03004043 hci_dev_unlock(hdev);
4044}
4045
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004046static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004047 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004048{
Johan Hedbergd9306502012-02-20 23:25:18 +02004049 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004050 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004051 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004052 int err;
4053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004054 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004055
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004056 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004057
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004058 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004059 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004060 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4061 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004062 goto unlock;
4063 }
4064
4065 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004066 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004067 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4068 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004069 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004070 }
4071
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004072 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04004073 if (!cmd) {
4074 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004075 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004076 }
4077
Andre Guedes0e05bba2013-04-30 15:29:33 -03004078 hci_req_init(&req, hdev);
4079
Johan Hedberg21a60d32014-06-10 14:05:58 +03004080 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004081
Johan Hedberg21a60d32014-06-10 14:05:58 +03004082 err = hci_req_run(&req, stop_discovery_complete);
4083 if (!err) {
4084 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004085 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004086 }
4087
Johan Hedberg21a60d32014-06-10 14:05:58 +03004088 mgmt_pending_remove(cmd);
4089
4090 /* If no HCI commands were sent we're done */
4091 if (err == -ENODATA) {
4092 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4093 &mgmt_cp->type, sizeof(mgmt_cp->type));
4094 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4095 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004096
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004097unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004098 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004099 return err;
4100}
4101
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004102static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004103 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004104{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004105 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004106 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004107 int err;
4108
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004109 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004110
Johan Hedberg561aafb2012-01-04 13:31:59 +02004111 hci_dev_lock(hdev);
4112
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004113 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004114 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4115 MGMT_STATUS_FAILED, &cp->addr,
4116 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004117 goto failed;
4118 }
4119
Johan Hedberga198e7b2012-02-17 14:27:06 +02004120 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004121 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004122 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4123 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4124 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004125 goto failed;
4126 }
4127
4128 if (cp->name_known) {
4129 e->name_state = NAME_KNOWN;
4130 list_del(&e->list);
4131 } else {
4132 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004133 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004134 }
4135
Johan Hedberge3846622013-01-09 15:29:33 +02004136 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4137 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004138
4139failed:
4140 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004141 return err;
4142}
4143
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004144static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004145 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004146{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004147 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004148 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004149 int err;
4150
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004151 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004152
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004153 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004154 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4155 MGMT_STATUS_INVALID_PARAMS,
4156 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004157
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004158 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004159
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004160 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4161 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004162 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004163 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004164 goto done;
4165 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004166
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004167 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4168 sk);
4169 status = MGMT_STATUS_SUCCESS;
4170
4171done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004172 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004173 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004174
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004175 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004176
4177 return err;
4178}
4179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004180static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004181 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004182{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004183 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004184 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004185 int err;
4186
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004187 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004188
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004189 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004190 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4191 MGMT_STATUS_INVALID_PARAMS,
4192 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004193
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004194 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004195
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004196 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4197 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004198 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004199 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004200 goto done;
4201 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004202
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004203 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4204 sk);
4205 status = MGMT_STATUS_SUCCESS;
4206
4207done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004208 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004209 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004210
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004211 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004212
4213 return err;
4214}
4215
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004216static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4217 u16 len)
4218{
4219 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004220 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004221 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004222 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004223
4224 BT_DBG("%s", hdev->name);
4225
Szymon Jancc72d4b82012-03-16 16:02:57 +01004226 source = __le16_to_cpu(cp->source);
4227
4228 if (source > 0x0002)
4229 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4230 MGMT_STATUS_INVALID_PARAMS);
4231
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004232 hci_dev_lock(hdev);
4233
Szymon Jancc72d4b82012-03-16 16:02:57 +01004234 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004235 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4236 hdev->devid_product = __le16_to_cpu(cp->product);
4237 hdev->devid_version = __le16_to_cpu(cp->version);
4238
4239 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4240
Johan Hedberg890ea892013-03-15 17:06:52 -05004241 hci_req_init(&req, hdev);
4242 update_eir(&req);
4243 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004244
4245 hci_dev_unlock(hdev);
4246
4247 return err;
4248}
4249
Johan Hedberg4375f102013-09-25 13:26:10 +03004250static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4251{
4252 struct cmd_lookup match = { NULL, hdev };
4253
4254 if (status) {
4255 u8 mgmt_err = mgmt_status(status);
4256
4257 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4258 cmd_status_rsp, &mgmt_err);
4259 return;
4260 }
4261
Johan Hedbergc93bd152014-07-08 15:07:48 +03004262 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4263 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4264 else
4265 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4266
Johan Hedberg4375f102013-09-25 13:26:10 +03004267 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4268 &match);
4269
4270 new_settings(hdev, match.sk);
4271
4272 if (match.sk)
4273 sock_put(match.sk);
4274}
4275
Marcel Holtmann21b51872013-10-10 09:47:53 -07004276static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4277 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004278{
4279 struct mgmt_mode *cp = data;
4280 struct pending_cmd *cmd;
4281 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004282 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004283 int err;
4284
4285 BT_DBG("request for %s", hdev->name);
4286
Johan Hedberge6fe7982013-10-02 15:45:22 +03004287 status = mgmt_le_support(hdev);
4288 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004289 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004290 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004291
4292 if (cp->val != 0x00 && cp->val != 0x01)
4293 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4294 MGMT_STATUS_INVALID_PARAMS);
4295
4296 hci_dev_lock(hdev);
4297
4298 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004299 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004300
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004301 /* The following conditions are ones which mean that we should
4302 * not do any HCI communication but directly send a mgmt
4303 * response to user space (after toggling the flag if
4304 * necessary).
4305 */
4306 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004307 hci_conn_num(hdev, LE_LINK) > 0 ||
4308 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4309 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004310 bool changed = false;
4311
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004312 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4313 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004314 changed = true;
4315 }
4316
4317 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4318 if (err < 0)
4319 goto unlock;
4320
4321 if (changed)
4322 err = new_settings(hdev, sk);
4323
4324 goto unlock;
4325 }
4326
4327 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4328 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4329 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4330 MGMT_STATUS_BUSY);
4331 goto unlock;
4332 }
4333
4334 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4335 if (!cmd) {
4336 err = -ENOMEM;
4337 goto unlock;
4338 }
4339
4340 hci_req_init(&req, hdev);
4341
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004342 if (val)
4343 enable_advertising(&req);
4344 else
4345 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004346
4347 err = hci_req_run(&req, set_advertising_complete);
4348 if (err < 0)
4349 mgmt_pending_remove(cmd);
4350
4351unlock:
4352 hci_dev_unlock(hdev);
4353 return err;
4354}
4355
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004356static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4357 void *data, u16 len)
4358{
4359 struct mgmt_cp_set_static_address *cp = data;
4360 int err;
4361
4362 BT_DBG("%s", hdev->name);
4363
Marcel Holtmann62af4442013-10-02 22:10:32 -07004364 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004365 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004366 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004367
4368 if (hdev_is_powered(hdev))
4369 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4370 MGMT_STATUS_REJECTED);
4371
4372 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4373 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4374 return cmd_status(sk, hdev->id,
4375 MGMT_OP_SET_STATIC_ADDRESS,
4376 MGMT_STATUS_INVALID_PARAMS);
4377
4378 /* Two most significant bits shall be set */
4379 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4380 return cmd_status(sk, hdev->id,
4381 MGMT_OP_SET_STATIC_ADDRESS,
4382 MGMT_STATUS_INVALID_PARAMS);
4383 }
4384
4385 hci_dev_lock(hdev);
4386
4387 bacpy(&hdev->static_addr, &cp->bdaddr);
4388
4389 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4390
4391 hci_dev_unlock(hdev);
4392
4393 return err;
4394}
4395
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004396static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4397 void *data, u16 len)
4398{
4399 struct mgmt_cp_set_scan_params *cp = data;
4400 __u16 interval, window;
4401 int err;
4402
4403 BT_DBG("%s", hdev->name);
4404
4405 if (!lmp_le_capable(hdev))
4406 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4407 MGMT_STATUS_NOT_SUPPORTED);
4408
4409 interval = __le16_to_cpu(cp->interval);
4410
4411 if (interval < 0x0004 || interval > 0x4000)
4412 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4413 MGMT_STATUS_INVALID_PARAMS);
4414
4415 window = __le16_to_cpu(cp->window);
4416
4417 if (window < 0x0004 || window > 0x4000)
4418 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4419 MGMT_STATUS_INVALID_PARAMS);
4420
Marcel Holtmann899e1072013-10-14 09:55:32 -07004421 if (window > interval)
4422 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4423 MGMT_STATUS_INVALID_PARAMS);
4424
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004425 hci_dev_lock(hdev);
4426
4427 hdev->le_scan_interval = interval;
4428 hdev->le_scan_window = window;
4429
4430 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4431
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004432 /* If background scan is running, restart it so new parameters are
4433 * loaded.
4434 */
4435 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4436 hdev->discovery.state == DISCOVERY_STOPPED) {
4437 struct hci_request req;
4438
4439 hci_req_init(&req, hdev);
4440
4441 hci_req_add_le_scan_disable(&req);
4442 hci_req_add_le_passive_scan(&req);
4443
4444 hci_req_run(&req, NULL);
4445 }
4446
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004447 hci_dev_unlock(hdev);
4448
4449 return err;
4450}
4451
Johan Hedberg33e38b32013-03-15 17:07:05 -05004452static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4453{
4454 struct pending_cmd *cmd;
4455
4456 BT_DBG("status 0x%02x", status);
4457
4458 hci_dev_lock(hdev);
4459
4460 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4461 if (!cmd)
4462 goto unlock;
4463
4464 if (status) {
4465 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4466 mgmt_status(status));
4467 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004468 struct mgmt_mode *cp = cmd->param;
4469
4470 if (cp->val)
4471 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4472 else
4473 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4474
Johan Hedberg33e38b32013-03-15 17:07:05 -05004475 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4476 new_settings(hdev, cmd->sk);
4477 }
4478
4479 mgmt_pending_remove(cmd);
4480
4481unlock:
4482 hci_dev_unlock(hdev);
4483}
4484
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004485static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004486 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004487{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004488 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004489 struct pending_cmd *cmd;
4490 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004491 int err;
4492
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004493 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004494
Johan Hedberg56f87902013-10-02 13:43:13 +03004495 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4496 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004497 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4498 MGMT_STATUS_NOT_SUPPORTED);
4499
Johan Hedberga7e80f22013-01-09 16:05:19 +02004500 if (cp->val != 0x00 && cp->val != 0x01)
4501 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4502 MGMT_STATUS_INVALID_PARAMS);
4503
Johan Hedberg5400c042012-02-21 16:40:33 +02004504 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004505 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004506 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004507
4508 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004509 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004510 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004511
4512 hci_dev_lock(hdev);
4513
Johan Hedberg05cbf292013-03-15 17:07:07 -05004514 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4515 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4516 MGMT_STATUS_BUSY);
4517 goto unlock;
4518 }
4519
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004520 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4521 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4522 hdev);
4523 goto unlock;
4524 }
4525
Johan Hedberg33e38b32013-03-15 17:07:05 -05004526 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4527 data, len);
4528 if (!cmd) {
4529 err = -ENOMEM;
4530 goto unlock;
4531 }
4532
4533 hci_req_init(&req, hdev);
4534
Johan Hedberg406d7802013-03-15 17:07:09 -05004535 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004536
4537 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004538 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004539 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004540 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004541 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004542 }
4543
Johan Hedberg33e38b32013-03-15 17:07:05 -05004544unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004545 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004546
Antti Julkuf6422ec2011-06-22 13:11:56 +03004547 return err;
4548}
4549
Johan Hedberg0663ca22013-10-02 13:43:14 +03004550static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4551{
4552 struct pending_cmd *cmd;
4553
4554 BT_DBG("status 0x%02x", status);
4555
4556 hci_dev_lock(hdev);
4557
4558 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4559 if (!cmd)
4560 goto unlock;
4561
4562 if (status) {
4563 u8 mgmt_err = mgmt_status(status);
4564
4565 /* We need to restore the flag if related HCI commands
4566 * failed.
4567 */
4568 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4569
4570 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4571 } else {
4572 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4573 new_settings(hdev, cmd->sk);
4574 }
4575
4576 mgmt_pending_remove(cmd);
4577
4578unlock:
4579 hci_dev_unlock(hdev);
4580}
4581
4582static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4583{
4584 struct mgmt_mode *cp = data;
4585 struct pending_cmd *cmd;
4586 struct hci_request req;
4587 int err;
4588
4589 BT_DBG("request for %s", hdev->name);
4590
4591 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4592 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4593 MGMT_STATUS_NOT_SUPPORTED);
4594
4595 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4596 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4597 MGMT_STATUS_REJECTED);
4598
4599 if (cp->val != 0x00 && cp->val != 0x01)
4600 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4601 MGMT_STATUS_INVALID_PARAMS);
4602
4603 hci_dev_lock(hdev);
4604
4605 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4606 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4607 goto unlock;
4608 }
4609
4610 if (!hdev_is_powered(hdev)) {
4611 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004612 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4613 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4614 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4615 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4616 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4617 }
4618
4619 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4620
4621 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4622 if (err < 0)
4623 goto unlock;
4624
4625 err = new_settings(hdev, sk);
4626 goto unlock;
4627 }
4628
4629 /* Reject disabling when powered on */
4630 if (!cp->val) {
4631 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4632 MGMT_STATUS_REJECTED);
4633 goto unlock;
4634 }
4635
4636 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4637 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4638 MGMT_STATUS_BUSY);
4639 goto unlock;
4640 }
4641
4642 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4643 if (!cmd) {
4644 err = -ENOMEM;
4645 goto unlock;
4646 }
4647
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004648 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004649 * generates the correct flags.
4650 */
4651 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4652
4653 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004654
Johan Hedberg432df052014-08-01 11:13:31 +03004655 write_fast_connectable(&req, false);
4656 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004657
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004658 /* Since only the advertising data flags will change, there
4659 * is no need to update the scan response data.
4660 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004661 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004662
Johan Hedberg0663ca22013-10-02 13:43:14 +03004663 err = hci_req_run(&req, set_bredr_complete);
4664 if (err < 0)
4665 mgmt_pending_remove(cmd);
4666
4667unlock:
4668 hci_dev_unlock(hdev);
4669 return err;
4670}
4671
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004672static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4673 void *data, u16 len)
4674{
4675 struct mgmt_mode *cp = data;
4676 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004677 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004678 int err;
4679
4680 BT_DBG("request for %s", hdev->name);
4681
Johan Hedberga3209692014-05-26 11:23:35 +03004682 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4683 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004684 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4685 MGMT_STATUS_NOT_SUPPORTED);
4686
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004687 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004688 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4689 MGMT_STATUS_INVALID_PARAMS);
4690
4691 hci_dev_lock(hdev);
4692
Johan Hedberga3209692014-05-26 11:23:35 +03004693 if (!hdev_is_powered(hdev) ||
4694 (!lmp_sc_capable(hdev) &&
4695 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4696 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004697 bool changed;
4698
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004699 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004700 changed = !test_and_set_bit(HCI_SC_ENABLED,
4701 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004702 if (cp->val == 0x02)
4703 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4704 else
4705 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4706 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004707 changed = test_and_clear_bit(HCI_SC_ENABLED,
4708 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004709 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4710 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004711
4712 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4713 if (err < 0)
4714 goto failed;
4715
4716 if (changed)
4717 err = new_settings(hdev, sk);
4718
4719 goto failed;
4720 }
4721
4722 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4723 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4724 MGMT_STATUS_BUSY);
4725 goto failed;
4726 }
4727
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004728 val = !!cp->val;
4729
4730 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4731 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004732 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4733 goto failed;
4734 }
4735
4736 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4737 if (!cmd) {
4738 err = -ENOMEM;
4739 goto failed;
4740 }
4741
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004742 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004743 if (err < 0) {
4744 mgmt_pending_remove(cmd);
4745 goto failed;
4746 }
4747
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004748 if (cp->val == 0x02)
4749 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4750 else
4751 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4752
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004753failed:
4754 hci_dev_unlock(hdev);
4755 return err;
4756}
4757
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004758static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4759 void *data, u16 len)
4760{
4761 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004762 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004763 int err;
4764
4765 BT_DBG("request for %s", hdev->name);
4766
Johan Hedbergb97109792014-06-24 14:00:28 +03004767 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004768 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4769 MGMT_STATUS_INVALID_PARAMS);
4770
4771 hci_dev_lock(hdev);
4772
4773 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004774 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4775 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004776 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004777 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4778 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004779
Johan Hedbergb97109792014-06-24 14:00:28 +03004780 if (cp->val == 0x02)
4781 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4782 &hdev->dev_flags);
4783 else
4784 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4785 &hdev->dev_flags);
4786
4787 if (hdev_is_powered(hdev) && use_changed &&
4788 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4789 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4790 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4791 sizeof(mode), &mode);
4792 }
4793
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004794 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4795 if (err < 0)
4796 goto unlock;
4797
4798 if (changed)
4799 err = new_settings(hdev, sk);
4800
4801unlock:
4802 hci_dev_unlock(hdev);
4803 return err;
4804}
4805
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004806static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4807 u16 len)
4808{
4809 struct mgmt_cp_set_privacy *cp = cp_data;
4810 bool changed;
4811 int err;
4812
4813 BT_DBG("request for %s", hdev->name);
4814
4815 if (!lmp_le_capable(hdev))
4816 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4817 MGMT_STATUS_NOT_SUPPORTED);
4818
4819 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4820 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4821 MGMT_STATUS_INVALID_PARAMS);
4822
4823 if (hdev_is_powered(hdev))
4824 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4825 MGMT_STATUS_REJECTED);
4826
4827 hci_dev_lock(hdev);
4828
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004829 /* If user space supports this command it is also expected to
4830 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4831 */
4832 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4833
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004834 if (cp->privacy) {
4835 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4836 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4837 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4838 } else {
4839 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4840 memset(hdev->irk, 0, sizeof(hdev->irk));
4841 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4842 }
4843
4844 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4845 if (err < 0)
4846 goto unlock;
4847
4848 if (changed)
4849 err = new_settings(hdev, sk);
4850
4851unlock:
4852 hci_dev_unlock(hdev);
4853 return err;
4854}
4855
Johan Hedberg41edf162014-02-18 10:19:35 +02004856static bool irk_is_valid(struct mgmt_irk_info *irk)
4857{
4858 switch (irk->addr.type) {
4859 case BDADDR_LE_PUBLIC:
4860 return true;
4861
4862 case BDADDR_LE_RANDOM:
4863 /* Two most significant bits shall be set */
4864 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4865 return false;
4866 return true;
4867 }
4868
4869 return false;
4870}
4871
4872static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4873 u16 len)
4874{
4875 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004876 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4877 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004878 u16 irk_count, expected_len;
4879 int i, err;
4880
4881 BT_DBG("request for %s", hdev->name);
4882
4883 if (!lmp_le_capable(hdev))
4884 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4885 MGMT_STATUS_NOT_SUPPORTED);
4886
4887 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004888 if (irk_count > max_irk_count) {
4889 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4890 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4891 MGMT_STATUS_INVALID_PARAMS);
4892 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004893
4894 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4895 if (expected_len != len) {
4896 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004897 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004898 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4899 MGMT_STATUS_INVALID_PARAMS);
4900 }
4901
4902 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4903
4904 for (i = 0; i < irk_count; i++) {
4905 struct mgmt_irk_info *key = &cp->irks[i];
4906
4907 if (!irk_is_valid(key))
4908 return cmd_status(sk, hdev->id,
4909 MGMT_OP_LOAD_IRKS,
4910 MGMT_STATUS_INVALID_PARAMS);
4911 }
4912
4913 hci_dev_lock(hdev);
4914
4915 hci_smp_irks_clear(hdev);
4916
4917 for (i = 0; i < irk_count; i++) {
4918 struct mgmt_irk_info *irk = &cp->irks[i];
4919 u8 addr_type;
4920
4921 if (irk->addr.type == BDADDR_LE_PUBLIC)
4922 addr_type = ADDR_LE_DEV_PUBLIC;
4923 else
4924 addr_type = ADDR_LE_DEV_RANDOM;
4925
4926 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4927 BDADDR_ANY);
4928 }
4929
4930 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4931
4932 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4933
4934 hci_dev_unlock(hdev);
4935
4936 return err;
4937}
4938
Johan Hedberg3f706b72013-01-20 14:27:16 +02004939static bool ltk_is_valid(struct mgmt_ltk_info *key)
4940{
4941 if (key->master != 0x00 && key->master != 0x01)
4942 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004943
4944 switch (key->addr.type) {
4945 case BDADDR_LE_PUBLIC:
4946 return true;
4947
4948 case BDADDR_LE_RANDOM:
4949 /* Two most significant bits shall be set */
4950 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4951 return false;
4952 return true;
4953 }
4954
4955 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004956}
4957
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004958static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004959 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004960{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004961 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004962 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4963 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004964 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004965 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004966
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004967 BT_DBG("request for %s", hdev->name);
4968
4969 if (!lmp_le_capable(hdev))
4970 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4971 MGMT_STATUS_NOT_SUPPORTED);
4972
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004973 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004974 if (key_count > max_key_count) {
4975 BT_ERR("load_ltks: too big key_count value %u", key_count);
4976 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4977 MGMT_STATUS_INVALID_PARAMS);
4978 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004979
4980 expected_len = sizeof(*cp) + key_count *
4981 sizeof(struct mgmt_ltk_info);
4982 if (expected_len != len) {
4983 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004984 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004985 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004986 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004987 }
4988
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004989 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004990
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004991 for (i = 0; i < key_count; i++) {
4992 struct mgmt_ltk_info *key = &cp->keys[i];
4993
Johan Hedberg3f706b72013-01-20 14:27:16 +02004994 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004995 return cmd_status(sk, hdev->id,
4996 MGMT_OP_LOAD_LONG_TERM_KEYS,
4997 MGMT_STATUS_INVALID_PARAMS);
4998 }
4999
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005000 hci_dev_lock(hdev);
5001
5002 hci_smp_ltks_clear(hdev);
5003
5004 for (i = 0; i < key_count; i++) {
5005 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005006 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005007
5008 if (key->addr.type == BDADDR_LE_PUBLIC)
5009 addr_type = ADDR_LE_DEV_PUBLIC;
5010 else
5011 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005012
Johan Hedberg61b43352014-05-29 19:36:53 +03005013 switch (key->type) {
5014 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005015 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005016 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005017 break;
5018 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005019 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005020 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005021 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005022 case MGMT_LTK_P256_UNAUTH:
5023 authenticated = 0x00;
5024 type = SMP_LTK_P256;
5025 break;
5026 case MGMT_LTK_P256_AUTH:
5027 authenticated = 0x01;
5028 type = SMP_LTK_P256;
5029 break;
5030 case MGMT_LTK_P256_DEBUG:
5031 authenticated = 0x00;
5032 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005033 default:
5034 continue;
5035 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005036
Johan Hedberg35d70272014-02-19 14:57:47 +02005037 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005038 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005039 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005040 }
5041
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005042 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5043 NULL, 0);
5044
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005045 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005046
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005047 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005048}
5049
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005050struct cmd_conn_lookup {
5051 struct hci_conn *conn;
5052 bool valid_tx_power;
5053 u8 mgmt_status;
5054};
5055
5056static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5057{
5058 struct cmd_conn_lookup *match = data;
5059 struct mgmt_cp_get_conn_info *cp;
5060 struct mgmt_rp_get_conn_info rp;
5061 struct hci_conn *conn = cmd->user_data;
5062
5063 if (conn != match->conn)
5064 return;
5065
5066 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5067
5068 memset(&rp, 0, sizeof(rp));
5069 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5070 rp.addr.type = cp->addr.type;
5071
5072 if (!match->mgmt_status) {
5073 rp.rssi = conn->rssi;
5074
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005075 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005076 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005077 rp.max_tx_power = conn->max_tx_power;
5078 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005079 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005080 rp.max_tx_power = HCI_TX_POWER_INVALID;
5081 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005082 }
5083
5084 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5085 match->mgmt_status, &rp, sizeof(rp));
5086
5087 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005088 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005089
5090 mgmt_pending_remove(cmd);
5091}
5092
5093static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5094{
5095 struct hci_cp_read_rssi *cp;
5096 struct hci_conn *conn;
5097 struct cmd_conn_lookup match;
5098 u16 handle;
5099
5100 BT_DBG("status 0x%02x", status);
5101
5102 hci_dev_lock(hdev);
5103
5104 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005105 * otherwise we assume it's not valid. At the moment we assume that
5106 * either both or none of current and max values are valid to keep code
5107 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005108 */
5109 match.valid_tx_power = !status;
5110
5111 /* Commands sent in request are either Read RSSI or Read Transmit Power
5112 * Level so we check which one was last sent to retrieve connection
5113 * handle. Both commands have handle as first parameter so it's safe to
5114 * cast data on the same command struct.
5115 *
5116 * First command sent is always Read RSSI and we fail only if it fails.
5117 * In other case we simply override error to indicate success as we
5118 * already remembered if TX power value is actually valid.
5119 */
5120 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5121 if (!cp) {
5122 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5123 status = 0;
5124 }
5125
5126 if (!cp) {
5127 BT_ERR("invalid sent_cmd in response");
5128 goto unlock;
5129 }
5130
5131 handle = __le16_to_cpu(cp->handle);
5132 conn = hci_conn_hash_lookup_handle(hdev, handle);
5133 if (!conn) {
5134 BT_ERR("unknown handle (%d) in response", handle);
5135 goto unlock;
5136 }
5137
5138 match.conn = conn;
5139 match.mgmt_status = mgmt_status(status);
5140
5141 /* Cache refresh is complete, now reply for mgmt request for given
5142 * connection only.
5143 */
5144 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5145 get_conn_info_complete, &match);
5146
5147unlock:
5148 hci_dev_unlock(hdev);
5149}
5150
5151static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5152 u16 len)
5153{
5154 struct mgmt_cp_get_conn_info *cp = data;
5155 struct mgmt_rp_get_conn_info rp;
5156 struct hci_conn *conn;
5157 unsigned long conn_info_age;
5158 int err = 0;
5159
5160 BT_DBG("%s", hdev->name);
5161
5162 memset(&rp, 0, sizeof(rp));
5163 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5164 rp.addr.type = cp->addr.type;
5165
5166 if (!bdaddr_type_is_valid(cp->addr.type))
5167 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5168 MGMT_STATUS_INVALID_PARAMS,
5169 &rp, sizeof(rp));
5170
5171 hci_dev_lock(hdev);
5172
5173 if (!hdev_is_powered(hdev)) {
5174 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5175 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5176 goto unlock;
5177 }
5178
5179 if (cp->addr.type == BDADDR_BREDR)
5180 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5181 &cp->addr.bdaddr);
5182 else
5183 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5184
5185 if (!conn || conn->state != BT_CONNECTED) {
5186 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5187 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5188 goto unlock;
5189 }
5190
5191 /* To avoid client trying to guess when to poll again for information we
5192 * calculate conn info age as random value between min/max set in hdev.
5193 */
5194 conn_info_age = hdev->conn_info_min_age +
5195 prandom_u32_max(hdev->conn_info_max_age -
5196 hdev->conn_info_min_age);
5197
5198 /* Query controller to refresh cached values if they are too old or were
5199 * never read.
5200 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005201 if (time_after(jiffies, conn->conn_info_timestamp +
5202 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005203 !conn->conn_info_timestamp) {
5204 struct hci_request req;
5205 struct hci_cp_read_tx_power req_txp_cp;
5206 struct hci_cp_read_rssi req_rssi_cp;
5207 struct pending_cmd *cmd;
5208
5209 hci_req_init(&req, hdev);
5210 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5211 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5212 &req_rssi_cp);
5213
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005214 /* For LE links TX power does not change thus we don't need to
5215 * query for it once value is known.
5216 */
5217 if (!bdaddr_type_is_le(cp->addr.type) ||
5218 conn->tx_power == HCI_TX_POWER_INVALID) {
5219 req_txp_cp.handle = cpu_to_le16(conn->handle);
5220 req_txp_cp.type = 0x00;
5221 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5222 sizeof(req_txp_cp), &req_txp_cp);
5223 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005224
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005225 /* Max TX power needs to be read only once per connection */
5226 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5227 req_txp_cp.handle = cpu_to_le16(conn->handle);
5228 req_txp_cp.type = 0x01;
5229 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5230 sizeof(req_txp_cp), &req_txp_cp);
5231 }
5232
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005233 err = hci_req_run(&req, conn_info_refresh_complete);
5234 if (err < 0)
5235 goto unlock;
5236
5237 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5238 data, len);
5239 if (!cmd) {
5240 err = -ENOMEM;
5241 goto unlock;
5242 }
5243
5244 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005245 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005246
5247 conn->conn_info_timestamp = jiffies;
5248 } else {
5249 /* Cache is valid, just reply with values cached in hci_conn */
5250 rp.rssi = conn->rssi;
5251 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005252 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005253
5254 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5255 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5256 }
5257
5258unlock:
5259 hci_dev_unlock(hdev);
5260 return err;
5261}
5262
Johan Hedberg95868422014-06-28 17:54:07 +03005263static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5264{
5265 struct mgmt_cp_get_clock_info *cp;
5266 struct mgmt_rp_get_clock_info rp;
5267 struct hci_cp_read_clock *hci_cp;
5268 struct pending_cmd *cmd;
5269 struct hci_conn *conn;
5270
5271 BT_DBG("%s status %u", hdev->name, status);
5272
5273 hci_dev_lock(hdev);
5274
5275 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5276 if (!hci_cp)
5277 goto unlock;
5278
5279 if (hci_cp->which) {
5280 u16 handle = __le16_to_cpu(hci_cp->handle);
5281 conn = hci_conn_hash_lookup_handle(hdev, handle);
5282 } else {
5283 conn = NULL;
5284 }
5285
5286 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5287 if (!cmd)
5288 goto unlock;
5289
5290 cp = cmd->param;
5291
5292 memset(&rp, 0, sizeof(rp));
5293 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5294
5295 if (status)
5296 goto send_rsp;
5297
5298 rp.local_clock = cpu_to_le32(hdev->clock);
5299
5300 if (conn) {
5301 rp.piconet_clock = cpu_to_le32(conn->clock);
5302 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5303 }
5304
5305send_rsp:
5306 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5307 &rp, sizeof(rp));
5308 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005309 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005310 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005311 hci_conn_put(conn);
5312 }
Johan Hedberg95868422014-06-28 17:54:07 +03005313
5314unlock:
5315 hci_dev_unlock(hdev);
5316}
5317
5318static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5319 u16 len)
5320{
5321 struct mgmt_cp_get_clock_info *cp = data;
5322 struct mgmt_rp_get_clock_info rp;
5323 struct hci_cp_read_clock hci_cp;
5324 struct pending_cmd *cmd;
5325 struct hci_request req;
5326 struct hci_conn *conn;
5327 int err;
5328
5329 BT_DBG("%s", hdev->name);
5330
5331 memset(&rp, 0, sizeof(rp));
5332 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5333 rp.addr.type = cp->addr.type;
5334
5335 if (cp->addr.type != BDADDR_BREDR)
5336 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5337 MGMT_STATUS_INVALID_PARAMS,
5338 &rp, sizeof(rp));
5339
5340 hci_dev_lock(hdev);
5341
5342 if (!hdev_is_powered(hdev)) {
5343 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5344 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5345 goto unlock;
5346 }
5347
5348 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5349 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5350 &cp->addr.bdaddr);
5351 if (!conn || conn->state != BT_CONNECTED) {
5352 err = cmd_complete(sk, hdev->id,
5353 MGMT_OP_GET_CLOCK_INFO,
5354 MGMT_STATUS_NOT_CONNECTED,
5355 &rp, sizeof(rp));
5356 goto unlock;
5357 }
5358 } else {
5359 conn = NULL;
5360 }
5361
5362 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5363 if (!cmd) {
5364 err = -ENOMEM;
5365 goto unlock;
5366 }
5367
5368 hci_req_init(&req, hdev);
5369
5370 memset(&hci_cp, 0, sizeof(hci_cp));
5371 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5372
5373 if (conn) {
5374 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005375 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005376
5377 hci_cp.handle = cpu_to_le16(conn->handle);
5378 hci_cp.which = 0x01; /* Piconet clock */
5379 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5380 }
5381
5382 err = hci_req_run(&req, get_clock_info_complete);
5383 if (err < 0)
5384 mgmt_pending_remove(cmd);
5385
5386unlock:
5387 hci_dev_unlock(hdev);
5388 return err;
5389}
5390
Marcel Holtmann8afef092014-06-29 22:28:34 +02005391static void device_added(struct sock *sk, struct hci_dev *hdev,
5392 bdaddr_t *bdaddr, u8 type, u8 action)
5393{
5394 struct mgmt_ev_device_added ev;
5395
5396 bacpy(&ev.addr.bdaddr, bdaddr);
5397 ev.addr.type = type;
5398 ev.action = action;
5399
5400 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5401}
5402
Marcel Holtmann2faade52014-06-29 19:44:03 +02005403static int add_device(struct sock *sk, struct hci_dev *hdev,
5404 void *data, u16 len)
5405{
5406 struct mgmt_cp_add_device *cp = data;
5407 u8 auto_conn, addr_type;
5408 int err;
5409
5410 BT_DBG("%s", hdev->name);
5411
Johan Hedberg66593582014-07-09 12:59:14 +03005412 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005413 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5414 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5415 MGMT_STATUS_INVALID_PARAMS,
5416 &cp->addr, sizeof(cp->addr));
5417
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005418 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005419 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5420 MGMT_STATUS_INVALID_PARAMS,
5421 &cp->addr, sizeof(cp->addr));
5422
5423 hci_dev_lock(hdev);
5424
Johan Hedberg66593582014-07-09 12:59:14 +03005425 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005426 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005427 if (cp->action != 0x01) {
5428 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5429 MGMT_STATUS_INVALID_PARAMS,
5430 &cp->addr, sizeof(cp->addr));
5431 goto unlock;
5432 }
5433
5434 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5435 cp->addr.type);
5436 if (err)
5437 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005438
Johan Hedberg432df052014-08-01 11:13:31 +03005439 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005440
Johan Hedberg66593582014-07-09 12:59:14 +03005441 goto added;
5442 }
5443
Marcel Holtmann2faade52014-06-29 19:44:03 +02005444 if (cp->addr.type == BDADDR_LE_PUBLIC)
5445 addr_type = ADDR_LE_DEV_PUBLIC;
5446 else
5447 addr_type = ADDR_LE_DEV_RANDOM;
5448
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005449 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005450 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005451 else if (cp->action == 0x01)
5452 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005453 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005454 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005455
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005456 /* If the connection parameters don't exist for this device,
5457 * they will be created and configured with defaults.
5458 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005459 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5460 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005461 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5462 MGMT_STATUS_FAILED,
5463 &cp->addr, sizeof(cp->addr));
5464 goto unlock;
5465 }
5466
Johan Hedberg66593582014-07-09 12:59:14 +03005467added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005468 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5469
Marcel Holtmann2faade52014-06-29 19:44:03 +02005470 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5471 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5472
5473unlock:
5474 hci_dev_unlock(hdev);
5475 return err;
5476}
5477
Marcel Holtmann8afef092014-06-29 22:28:34 +02005478static void device_removed(struct sock *sk, struct hci_dev *hdev,
5479 bdaddr_t *bdaddr, u8 type)
5480{
5481 struct mgmt_ev_device_removed ev;
5482
5483 bacpy(&ev.addr.bdaddr, bdaddr);
5484 ev.addr.type = type;
5485
5486 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5487}
5488
Marcel Holtmann2faade52014-06-29 19:44:03 +02005489static int remove_device(struct sock *sk, struct hci_dev *hdev,
5490 void *data, u16 len)
5491{
5492 struct mgmt_cp_remove_device *cp = data;
5493 int err;
5494
5495 BT_DBG("%s", hdev->name);
5496
5497 hci_dev_lock(hdev);
5498
5499 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005500 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005501 u8 addr_type;
5502
Johan Hedberg66593582014-07-09 12:59:14 +03005503 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005504 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5505 MGMT_STATUS_INVALID_PARAMS,
5506 &cp->addr, sizeof(cp->addr));
5507 goto unlock;
5508 }
5509
Johan Hedberg66593582014-07-09 12:59:14 +03005510 if (cp->addr.type == BDADDR_BREDR) {
5511 err = hci_bdaddr_list_del(&hdev->whitelist,
5512 &cp->addr.bdaddr,
5513 cp->addr.type);
5514 if (err) {
5515 err = cmd_complete(sk, hdev->id,
5516 MGMT_OP_REMOVE_DEVICE,
5517 MGMT_STATUS_INVALID_PARAMS,
5518 &cp->addr, sizeof(cp->addr));
5519 goto unlock;
5520 }
5521
Johan Hedberg432df052014-08-01 11:13:31 +03005522 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005523
Johan Hedberg66593582014-07-09 12:59:14 +03005524 device_removed(sk, hdev, &cp->addr.bdaddr,
5525 cp->addr.type);
5526 goto complete;
5527 }
5528
Marcel Holtmann2faade52014-06-29 19:44:03 +02005529 if (cp->addr.type == BDADDR_LE_PUBLIC)
5530 addr_type = ADDR_LE_DEV_PUBLIC;
5531 else
5532 addr_type = ADDR_LE_DEV_RANDOM;
5533
Johan Hedbergc71593d2014-07-02 17:37:28 +03005534 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5535 addr_type);
5536 if (!params) {
5537 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5538 MGMT_STATUS_INVALID_PARAMS,
5539 &cp->addr, sizeof(cp->addr));
5540 goto unlock;
5541 }
5542
5543 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5544 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5545 MGMT_STATUS_INVALID_PARAMS,
5546 &cp->addr, sizeof(cp->addr));
5547 goto unlock;
5548 }
5549
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005550 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005551 list_del(&params->list);
5552 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005553 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005554
5555 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005556 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005557 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005558 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005559
Marcel Holtmann2faade52014-06-29 19:44:03 +02005560 if (cp->addr.type) {
5561 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5562 MGMT_STATUS_INVALID_PARAMS,
5563 &cp->addr, sizeof(cp->addr));
5564 goto unlock;
5565 }
5566
Johan Hedberg66593582014-07-09 12:59:14 +03005567 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5568 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5569 list_del(&b->list);
5570 kfree(b);
5571 }
5572
Johan Hedberg432df052014-08-01 11:13:31 +03005573 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005574
Johan Hedberg19de0822014-07-06 13:06:51 +03005575 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5576 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5577 continue;
5578 device_removed(sk, hdev, &p->addr, p->addr_type);
5579 list_del(&p->action);
5580 list_del(&p->list);
5581 kfree(p);
5582 }
5583
5584 BT_DBG("All LE connection parameters were removed");
5585
5586 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005587 }
5588
Johan Hedberg66593582014-07-09 12:59:14 +03005589complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005590 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5591 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5592
5593unlock:
5594 hci_dev_unlock(hdev);
5595 return err;
5596}
5597
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005598static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5599 u16 len)
5600{
5601 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005602 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5603 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005604 u16 param_count, expected_len;
5605 int i;
5606
5607 if (!lmp_le_capable(hdev))
5608 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5609 MGMT_STATUS_NOT_SUPPORTED);
5610
5611 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005612 if (param_count > max_param_count) {
5613 BT_ERR("load_conn_param: too big param_count value %u",
5614 param_count);
5615 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5616 MGMT_STATUS_INVALID_PARAMS);
5617 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005618
5619 expected_len = sizeof(*cp) + param_count *
5620 sizeof(struct mgmt_conn_param);
5621 if (expected_len != len) {
5622 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5623 expected_len, len);
5624 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5625 MGMT_STATUS_INVALID_PARAMS);
5626 }
5627
5628 BT_DBG("%s param_count %u", hdev->name, param_count);
5629
5630 hci_dev_lock(hdev);
5631
5632 hci_conn_params_clear_disabled(hdev);
5633
5634 for (i = 0; i < param_count; i++) {
5635 struct mgmt_conn_param *param = &cp->params[i];
5636 struct hci_conn_params *hci_param;
5637 u16 min, max, latency, timeout;
5638 u8 addr_type;
5639
5640 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5641 param->addr.type);
5642
5643 if (param->addr.type == BDADDR_LE_PUBLIC) {
5644 addr_type = ADDR_LE_DEV_PUBLIC;
5645 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5646 addr_type = ADDR_LE_DEV_RANDOM;
5647 } else {
5648 BT_ERR("Ignoring invalid connection parameters");
5649 continue;
5650 }
5651
5652 min = le16_to_cpu(param->min_interval);
5653 max = le16_to_cpu(param->max_interval);
5654 latency = le16_to_cpu(param->latency);
5655 timeout = le16_to_cpu(param->timeout);
5656
5657 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5658 min, max, latency, timeout);
5659
5660 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5661 BT_ERR("Ignoring invalid connection parameters");
5662 continue;
5663 }
5664
5665 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5666 addr_type);
5667 if (!hci_param) {
5668 BT_ERR("Failed to add connection parameters");
5669 continue;
5670 }
5671
5672 hci_param->conn_min_interval = min;
5673 hci_param->conn_max_interval = max;
5674 hci_param->conn_latency = latency;
5675 hci_param->supervision_timeout = timeout;
5676 }
5677
5678 hci_dev_unlock(hdev);
5679
5680 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5681}
5682
Marcel Holtmanndbece372014-07-04 18:11:55 +02005683static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5684 void *data, u16 len)
5685{
5686 struct mgmt_cp_set_external_config *cp = data;
5687 bool changed;
5688 int err;
5689
5690 BT_DBG("%s", hdev->name);
5691
5692 if (hdev_is_powered(hdev))
5693 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5694 MGMT_STATUS_REJECTED);
5695
5696 if (cp->config != 0x00 && cp->config != 0x01)
5697 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5698 MGMT_STATUS_INVALID_PARAMS);
5699
5700 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5701 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5702 MGMT_STATUS_NOT_SUPPORTED);
5703
5704 hci_dev_lock(hdev);
5705
5706 if (cp->config)
5707 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5708 &hdev->dev_flags);
5709 else
5710 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5711 &hdev->dev_flags);
5712
5713 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5714 if (err < 0)
5715 goto unlock;
5716
5717 if (!changed)
5718 goto unlock;
5719
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005720 err = new_options(hdev, sk);
5721
Marcel Holtmanndbece372014-07-04 18:11:55 +02005722 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5723 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005724
5725 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5726 set_bit(HCI_CONFIG, &hdev->dev_flags);
5727 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5728
5729 queue_work(hdev->req_workqueue, &hdev->power_on);
5730 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005731 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005732 mgmt_index_added(hdev);
5733 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005734 }
5735
5736unlock:
5737 hci_dev_unlock(hdev);
5738 return err;
5739}
5740
Marcel Holtmann9713c172014-07-06 12:11:15 +02005741static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5742 void *data, u16 len)
5743{
5744 struct mgmt_cp_set_public_address *cp = data;
5745 bool changed;
5746 int err;
5747
5748 BT_DBG("%s", hdev->name);
5749
5750 if (hdev_is_powered(hdev))
5751 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5752 MGMT_STATUS_REJECTED);
5753
5754 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5755 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5756 MGMT_STATUS_INVALID_PARAMS);
5757
5758 if (!hdev->set_bdaddr)
5759 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5760 MGMT_STATUS_NOT_SUPPORTED);
5761
5762 hci_dev_lock(hdev);
5763
5764 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5765 bacpy(&hdev->public_addr, &cp->bdaddr);
5766
5767 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5768 if (err < 0)
5769 goto unlock;
5770
5771 if (!changed)
5772 goto unlock;
5773
5774 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5775 err = new_options(hdev, sk);
5776
5777 if (is_configured(hdev)) {
5778 mgmt_index_removed(hdev);
5779
5780 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5781
5782 set_bit(HCI_CONFIG, &hdev->dev_flags);
5783 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5784
5785 queue_work(hdev->req_workqueue, &hdev->power_on);
5786 }
5787
5788unlock:
5789 hci_dev_unlock(hdev);
5790 return err;
5791}
5792
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005793static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005794 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5795 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005796 bool var_len;
5797 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005798} mgmt_handlers[] = {
5799 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005800 { read_version, false, MGMT_READ_VERSION_SIZE },
5801 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5802 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5803 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5804 { set_powered, false, MGMT_SETTING_SIZE },
5805 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5806 { set_connectable, false, MGMT_SETTING_SIZE },
5807 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005808 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005809 { set_link_security, false, MGMT_SETTING_SIZE },
5810 { set_ssp, false, MGMT_SETTING_SIZE },
5811 { set_hs, false, MGMT_SETTING_SIZE },
5812 { set_le, false, MGMT_SETTING_SIZE },
5813 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5814 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5815 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5816 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5817 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5818 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5819 { disconnect, false, MGMT_DISCONNECT_SIZE },
5820 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5821 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5822 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5823 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5824 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5825 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5826 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5827 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5828 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5829 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5830 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5831 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005832 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005833 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5834 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5835 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5836 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5837 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5838 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005839 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005840 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005841 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005842 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005843 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005844 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005845 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005846 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005847 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005848 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005849 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005850 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5851 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005852 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5853 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005854 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005855 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005856 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005857 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005858};
5859
Johan Hedberg03811012010-12-08 00:21:06 +02005860int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5861{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005862 void *buf;
5863 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005864 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005865 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005866 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005867 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005868 int err;
5869
5870 BT_DBG("got %zu bytes", msglen);
5871
5872 if (msglen < sizeof(*hdr))
5873 return -EINVAL;
5874
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005875 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005876 if (!buf)
5877 return -ENOMEM;
5878
5879 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5880 err = -EFAULT;
5881 goto done;
5882 }
5883
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005884 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005885 opcode = __le16_to_cpu(hdr->opcode);
5886 index = __le16_to_cpu(hdr->index);
5887 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005888
5889 if (len != msglen - sizeof(*hdr)) {
5890 err = -EINVAL;
5891 goto done;
5892 }
5893
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005894 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005895 hdev = hci_dev_get(index);
5896 if (!hdev) {
5897 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005898 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005899 goto done;
5900 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005901
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005902 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005903 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005904 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005905 err = cmd_status(sk, index, opcode,
5906 MGMT_STATUS_INVALID_INDEX);
5907 goto done;
5908 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005909
5910 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005911 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005912 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5913 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005914 err = cmd_status(sk, index, opcode,
5915 MGMT_STATUS_INVALID_INDEX);
5916 goto done;
5917 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005918 }
5919
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005920 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005921 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005922 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005923 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005924 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005925 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005926 }
5927
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005928 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5929 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5930 err = cmd_status(sk, index, opcode,
5931 MGMT_STATUS_INVALID_INDEX);
5932 goto done;
5933 }
5934
5935 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5936 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005937 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005938 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005939 goto done;
5940 }
5941
Johan Hedbergbe22b542012-03-01 22:24:41 +02005942 handler = &mgmt_handlers[opcode];
5943
5944 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005945 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005946 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005947 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005948 goto done;
5949 }
5950
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005951 if (hdev)
5952 mgmt_init_hdev(sk, hdev);
5953
5954 cp = buf + sizeof(*hdr);
5955
Johan Hedbergbe22b542012-03-01 22:24:41 +02005956 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005957 if (err < 0)
5958 goto done;
5959
Johan Hedberg03811012010-12-08 00:21:06 +02005960 err = msglen;
5961
5962done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005963 if (hdev)
5964 hci_dev_put(hdev);
5965
Johan Hedberg03811012010-12-08 00:21:06 +02005966 kfree(buf);
5967 return err;
5968}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005969
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005970void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005971{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005972 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005973 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005974
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005975 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5976 return;
5977
5978 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5979 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5980 else
5981 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005982}
5983
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005984void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005985{
Johan Hedberg5f159032012-03-02 03:13:19 +02005986 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005987
Marcel Holtmann1514b892013-10-06 08:25:01 -07005988 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005989 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005990
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005991 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5992 return;
5993
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02005994 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02005995
Marcel Holtmannedd38962014-07-02 21:30:55 +02005996 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5997 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
5998 else
5999 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006000}
6001
Andre Guedes6046dc32014-02-26 20:21:51 -03006002/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006003static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006004{
6005 struct hci_conn_params *p;
6006
6007 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006008 /* Needed for AUTO_OFF case where might not "really"
6009 * have been powered off.
6010 */
6011 list_del_init(&p->action);
6012
6013 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006014 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006015 case HCI_AUTO_CONN_ALWAYS:
6016 list_add(&p->action, &hdev->pend_le_conns);
6017 break;
6018 case HCI_AUTO_CONN_REPORT:
6019 list_add(&p->action, &hdev->pend_le_reports);
6020 break;
6021 default:
6022 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006023 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006024 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006025
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006026 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006027}
6028
Johan Hedberg229ab392013-03-15 17:06:53 -05006029static void powered_complete(struct hci_dev *hdev, u8 status)
6030{
6031 struct cmd_lookup match = { NULL, hdev };
6032
6033 BT_DBG("status 0x%02x", status);
6034
6035 hci_dev_lock(hdev);
6036
Johan Hedbergd7347f32014-07-04 12:37:23 +03006037 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006038
Johan Hedberg229ab392013-03-15 17:06:53 -05006039 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6040
6041 new_settings(hdev, match.sk);
6042
6043 hci_dev_unlock(hdev);
6044
6045 if (match.sk)
6046 sock_put(match.sk);
6047}
6048
Johan Hedberg70da6242013-03-15 17:06:51 -05006049static int powered_update_hci(struct hci_dev *hdev)
6050{
Johan Hedberg890ea892013-03-15 17:06:52 -05006051 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006052 u8 link_sec;
6053
Johan Hedberg890ea892013-03-15 17:06:52 -05006054 hci_req_init(&req, hdev);
6055
Johan Hedberg70da6242013-03-15 17:06:51 -05006056 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6057 !lmp_host_ssp_capable(hdev)) {
6058 u8 ssp = 1;
6059
Johan Hedberg890ea892013-03-15 17:06:52 -05006060 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006061 }
6062
Johan Hedbergc73eee92013-04-19 18:35:21 +03006063 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6064 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006065 struct hci_cp_write_le_host_supported cp;
6066
Marcel Holtmann32226e42014-07-24 20:04:16 +02006067 cp.le = 0x01;
6068 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006069
6070 /* Check first if we already have the right
6071 * host state (host features set)
6072 */
6073 if (cp.le != lmp_host_le_capable(hdev) ||
6074 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006075 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6076 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006077 }
6078
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006079 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006080 /* Make sure the controller has a good default for
6081 * advertising data. This also applies to the case
6082 * where BR/EDR was toggled during the AUTO_OFF phase.
6083 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006084 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006085 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006086 update_scan_rsp_data(&req);
6087 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006088
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006089 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6090 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006091 }
6092
Johan Hedberg70da6242013-03-15 17:06:51 -05006093 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6094 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006095 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6096 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006097
6098 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006099 write_fast_connectable(&req, false);
6100 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006101 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006102 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006103 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006104 }
6105
Johan Hedberg229ab392013-03-15 17:06:53 -05006106 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006107}
6108
Johan Hedberg744cf192011-11-08 20:40:14 +02006109int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006110{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006111 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006112 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6113 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006114 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006115
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006116 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6117 return 0;
6118
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006119 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006120 if (powered_update_hci(hdev) == 0)
6121 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006122
Johan Hedberg229ab392013-03-15 17:06:53 -05006123 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6124 &match);
6125 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006126 }
6127
Johan Hedberg229ab392013-03-15 17:06:53 -05006128 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006129 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006130
6131 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6132 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6133 zero_cod, sizeof(zero_cod), NULL);
6134
6135new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006136 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006137
6138 if (match.sk)
6139 sock_put(match.sk);
6140
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006141 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006142}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006143
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006144void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006145{
6146 struct pending_cmd *cmd;
6147 u8 status;
6148
6149 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6150 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006151 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006152
6153 if (err == -ERFKILL)
6154 status = MGMT_STATUS_RFKILLED;
6155 else
6156 status = MGMT_STATUS_FAILED;
6157
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006158 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006159
6160 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006161}
6162
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006163void mgmt_discoverable_timeout(struct hci_dev *hdev)
6164{
6165 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006166
6167 hci_dev_lock(hdev);
6168
6169 /* When discoverable timeout triggers, then just make sure
6170 * the limited discoverable flag is cleared. Even in the case
6171 * of a timeout triggered from general discoverable, it is
6172 * safe to unconditionally clear the flag.
6173 */
6174 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006175 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006176
6177 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006178 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6179 u8 scan = SCAN_PAGE;
6180 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6181 sizeof(scan), &scan);
6182 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006183 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006184 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006185 hci_req_run(&req, NULL);
6186
6187 hdev->discov_timeout = 0;
6188
Johan Hedberg9a43e252013-10-20 19:00:07 +03006189 new_settings(hdev, NULL);
6190
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006191 hci_dev_unlock(hdev);
6192}
6193
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006194void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6195 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006196{
Johan Hedberg86742e12011-11-07 23:13:38 +02006197 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006198
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006199 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006200
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006201 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006202 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006203 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006204 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006205 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006206 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006207
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006208 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006209}
Johan Hedbergf7520542011-01-20 12:34:39 +02006210
Johan Hedbergd7b25452014-05-23 13:19:53 +03006211static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6212{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006213 switch (ltk->type) {
6214 case SMP_LTK:
6215 case SMP_LTK_SLAVE:
6216 if (ltk->authenticated)
6217 return MGMT_LTK_AUTHENTICATED;
6218 return MGMT_LTK_UNAUTHENTICATED;
6219 case SMP_LTK_P256:
6220 if (ltk->authenticated)
6221 return MGMT_LTK_P256_AUTH;
6222 return MGMT_LTK_P256_UNAUTH;
6223 case SMP_LTK_P256_DEBUG:
6224 return MGMT_LTK_P256_DEBUG;
6225 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006226
6227 return MGMT_LTK_UNAUTHENTICATED;
6228}
6229
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006230void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006231{
6232 struct mgmt_ev_new_long_term_key ev;
6233
6234 memset(&ev, 0, sizeof(ev));
6235
Marcel Holtmann5192d302014-02-19 17:11:58 -08006236 /* Devices using resolvable or non-resolvable random addresses
6237 * without providing an indentity resolving key don't require
6238 * to store long term keys. Their addresses will change the
6239 * next time around.
6240 *
6241 * Only when a remote device provides an identity address
6242 * make sure the long term key is stored. If the remote
6243 * identity is known, the long term keys are internally
6244 * mapped to the identity address. So allow static random
6245 * and public addresses here.
6246 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006247 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6248 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6249 ev.store_hint = 0x00;
6250 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006251 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006252
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006253 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006254 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006255 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006256 ev.key.enc_size = key->enc_size;
6257 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006258 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006259
Johan Hedberg2ceba532014-06-16 19:25:16 +03006260 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006261 ev.key.master = 1;
6262
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006263 memcpy(ev.key.val, key->val, sizeof(key->val));
6264
Marcel Holtmann083368f2013-10-15 14:26:29 -07006265 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006266}
6267
Johan Hedberg95fbac82014-02-19 15:18:31 +02006268void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6269{
6270 struct mgmt_ev_new_irk ev;
6271
6272 memset(&ev, 0, sizeof(ev));
6273
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006274 /* For identity resolving keys from devices that are already
6275 * using a public address or static random address, do not
6276 * ask for storing this key. The identity resolving key really
6277 * is only mandatory for devices using resovlable random
6278 * addresses.
6279 *
6280 * Storing all identity resolving keys has the downside that
6281 * they will be also loaded on next boot of they system. More
6282 * identity resolving keys, means more time during scanning is
6283 * needed to actually resolve these addresses.
6284 */
6285 if (bacmp(&irk->rpa, BDADDR_ANY))
6286 ev.store_hint = 0x01;
6287 else
6288 ev.store_hint = 0x00;
6289
Johan Hedberg95fbac82014-02-19 15:18:31 +02006290 bacpy(&ev.rpa, &irk->rpa);
6291 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6292 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6293 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6294
6295 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6296}
6297
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006298void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6299 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006300{
6301 struct mgmt_ev_new_csrk ev;
6302
6303 memset(&ev, 0, sizeof(ev));
6304
6305 /* Devices using resolvable or non-resolvable random addresses
6306 * without providing an indentity resolving key don't require
6307 * to store signature resolving keys. Their addresses will change
6308 * the next time around.
6309 *
6310 * Only when a remote device provides an identity address
6311 * make sure the signature resolving key is stored. So allow
6312 * static random and public addresses here.
6313 */
6314 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6315 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6316 ev.store_hint = 0x00;
6317 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006318 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006319
6320 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6321 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6322 ev.key.master = csrk->master;
6323 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6324
6325 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6326}
6327
Andre Guedesffb5a8272014-07-01 18:10:11 -03006328void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006329 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6330 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006331{
6332 struct mgmt_ev_new_conn_param ev;
6333
Johan Hedbergc103aea2014-07-02 17:37:34 +03006334 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6335 return;
6336
Andre Guedesffb5a8272014-07-01 18:10:11 -03006337 memset(&ev, 0, sizeof(ev));
6338 bacpy(&ev.addr.bdaddr, bdaddr);
6339 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006340 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006341 ev.min_interval = cpu_to_le16(min_interval);
6342 ev.max_interval = cpu_to_le16(max_interval);
6343 ev.latency = cpu_to_le16(latency);
6344 ev.timeout = cpu_to_le16(timeout);
6345
6346 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6347}
6348
Marcel Holtmann94933992013-10-15 10:26:39 -07006349static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6350 u8 data_len)
6351{
6352 eir[eir_len++] = sizeof(type) + data_len;
6353 eir[eir_len++] = type;
6354 memcpy(&eir[eir_len], data, data_len);
6355 eir_len += data_len;
6356
6357 return eir_len;
6358}
6359
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006360void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6361 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006362{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006363 char buf[512];
6364 struct mgmt_ev_device_connected *ev = (void *) buf;
6365 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006366
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006367 bacpy(&ev->addr.bdaddr, &conn->dst);
6368 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006369
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006370 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006371
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006372 /* We must ensure that the EIR Data fields are ordered and
6373 * unique. Keep it simple for now and avoid the problem by not
6374 * adding any BR/EDR data to the LE adv.
6375 */
6376 if (conn->le_adv_data_len > 0) {
6377 memcpy(&ev->eir[eir_len],
6378 conn->le_adv_data, conn->le_adv_data_len);
6379 eir_len = conn->le_adv_data_len;
6380 } else {
6381 if (name_len > 0)
6382 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6383 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006384
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006385 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006386 eir_len = eir_append_data(ev->eir, eir_len,
6387 EIR_CLASS_OF_DEV,
6388 conn->dev_class, 3);
6389 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006390
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006391 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006392
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006393 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6394 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006395}
6396
Johan Hedberg8962ee72011-01-20 12:40:27 +02006397static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6398{
Szymon Jancc68fb7f2011-03-22 13:12:19 +01006399 struct mgmt_cp_disconnect *cp = cmd->param;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006400 struct sock **sk = data;
Johan Hedberga38528f2011-01-22 06:46:43 +02006401 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006402
Johan Hedberg88c3df12012-02-09 14:27:38 +02006403 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6404 rp.addr.type = cp->addr.type;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006405
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006406 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006407 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006408
6409 *sk = cmd->sk;
6410 sock_hold(*sk);
6411
Johan Hedberga664b5b2011-02-19 12:06:02 -03006412 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006413}
6414
Johan Hedberg124f6e32012-02-09 13:50:12 +02006415static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006416{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006417 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006418 struct mgmt_cp_unpair_device *cp = cmd->param;
6419 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006420
6421 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006422 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6423 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006424
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006425 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6426
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006427 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006428
6429 mgmt_pending_remove(cmd);
6430}
6431
Johan Hedberg84c61d92014-08-01 11:13:30 +03006432bool mgmt_powering_down(struct hci_dev *hdev)
6433{
6434 struct pending_cmd *cmd;
6435 struct mgmt_mode *cp;
6436
6437 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6438 if (!cmd)
6439 return false;
6440
6441 cp = cmd->param;
6442 if (!cp->val)
6443 return true;
6444
6445 return false;
6446}
6447
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006448void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006449 u8 link_type, u8 addr_type, u8 reason,
6450 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006451{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006452 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006453 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006454
Johan Hedberg84c61d92014-08-01 11:13:30 +03006455 /* The connection is still in hci_conn_hash so test for 1
6456 * instead of 0 to know if this is the last one.
6457 */
6458 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6459 cancel_delayed_work(&hdev->power_off);
6460 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006461 }
6462
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006463 if (!mgmt_connected)
6464 return;
6465
Andre Guedes57eb7762013-10-30 19:01:41 -03006466 if (link_type != ACL_LINK && link_type != LE_LINK)
6467 return;
6468
Johan Hedberg744cf192011-11-08 20:40:14 +02006469 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006470
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006471 bacpy(&ev.addr.bdaddr, bdaddr);
6472 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6473 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006474
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006475 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006476
6477 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006478 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006479
Johan Hedberg124f6e32012-02-09 13:50:12 +02006480 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006481 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006482}
6483
Marcel Holtmann78929242013-10-06 23:55:47 -07006484void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6485 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006486{
Andre Guedes3655bba2013-10-30 19:01:40 -03006487 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6488 struct mgmt_cp_disconnect *cp;
Johan Hedberg88c3df12012-02-09 14:27:38 +02006489 struct mgmt_rp_disconnect rp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006490 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006491
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006492 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6493 hdev);
6494
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006495 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006496 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006497 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006498
Andre Guedes3655bba2013-10-30 19:01:40 -03006499 cp = cmd->param;
6500
6501 if (bacmp(bdaddr, &cp->addr.bdaddr))
6502 return;
6503
6504 if (cp->addr.type != bdaddr_type)
6505 return;
6506
Johan Hedberg88c3df12012-02-09 14:27:38 +02006507 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes3655bba2013-10-30 19:01:40 -03006508 rp.addr.type = bdaddr_type;
Johan Hedberg37d9ef72011-11-10 15:54:39 +02006509
Marcel Holtmann78929242013-10-06 23:55:47 -07006510 cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
6511 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02006512
Johan Hedberga664b5b2011-02-19 12:06:02 -03006513 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006514}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006515
Marcel Holtmann445608d2013-10-06 23:55:48 -07006516void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6517 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006518{
6519 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006520
Johan Hedberg84c61d92014-08-01 11:13:30 +03006521 /* The connection is still in hci_conn_hash so test for 1
6522 * instead of 0 to know if this is the last one.
6523 */
6524 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6525 cancel_delayed_work(&hdev->power_off);
6526 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006527 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006528
Johan Hedberg4c659c32011-11-07 23:13:39 +02006529 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006530 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006531 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006532
Marcel Holtmann445608d2013-10-06 23:55:48 -07006533 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006534}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006535
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006536void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006537{
6538 struct mgmt_ev_pin_code_request ev;
6539
Johan Hedbergd8457692012-02-17 14:24:57 +02006540 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006541 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006542 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006543
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006544 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006545}
6546
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006547void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6548 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006549{
6550 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006551 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006552
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006553 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006554 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006555 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006556
Johan Hedbergd8457692012-02-17 14:24:57 +02006557 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006558 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006559
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006560 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6561 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006562
Johan Hedberga664b5b2011-02-19 12:06:02 -03006563 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006564}
6565
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006566void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6567 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006568{
6569 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006570 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006571
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006572 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006573 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006574 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006575
Johan Hedbergd8457692012-02-17 14:24:57 +02006576 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006577 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006578
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006579 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6580 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006581
Johan Hedberga664b5b2011-02-19 12:06:02 -03006582 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006583}
Johan Hedberga5c29682011-02-19 12:05:57 -03006584
Johan Hedberg744cf192011-11-08 20:40:14 +02006585int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006586 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006587 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006588{
6589 struct mgmt_ev_user_confirm_request ev;
6590
Johan Hedberg744cf192011-11-08 20:40:14 +02006591 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006592
Johan Hedberg272d90d2012-02-09 15:26:12 +02006593 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006594 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006595 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006596 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006597
Johan Hedberg744cf192011-11-08 20:40:14 +02006598 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006599 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006600}
6601
Johan Hedberg272d90d2012-02-09 15:26:12 +02006602int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006603 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006604{
6605 struct mgmt_ev_user_passkey_request ev;
6606
6607 BT_DBG("%s", hdev->name);
6608
Johan Hedberg272d90d2012-02-09 15:26:12 +02006609 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006610 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006611
6612 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006613 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006614}
6615
Brian Gix0df4c182011-11-16 13:53:13 -08006616static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006617 u8 link_type, u8 addr_type, u8 status,
6618 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006619{
6620 struct pending_cmd *cmd;
6621 struct mgmt_rp_user_confirm_reply rp;
6622 int err;
6623
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006624 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006625 if (!cmd)
6626 return -ENOENT;
6627
Johan Hedberg272d90d2012-02-09 15:26:12 +02006628 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006629 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b2182012-02-18 15:07:59 +02006630 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006631 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006632
Johan Hedberga664b5b2011-02-19 12:06:02 -03006633 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006634
6635 return err;
6636}
6637
Johan Hedberg744cf192011-11-08 20:40:14 +02006638int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006639 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006640{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006641 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006643}
6644
Johan Hedberg272d90d2012-02-09 15:26:12 +02006645int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006646 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006647{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006648 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006649 status,
6650 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006651}
Johan Hedberg2a611692011-02-19 12:06:00 -03006652
Brian Gix604086b2011-11-23 08:28:33 -08006653int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006654 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006655{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006656 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006657 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006658}
6659
Johan Hedberg272d90d2012-02-09 15:26:12 +02006660int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006661 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006662{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006663 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006664 status,
6665 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006666}
6667
Johan Hedberg92a25252012-09-06 18:39:26 +03006668int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6669 u8 link_type, u8 addr_type, u32 passkey,
6670 u8 entered)
6671{
6672 struct mgmt_ev_passkey_notify ev;
6673
6674 BT_DBG("%s", hdev->name);
6675
6676 bacpy(&ev.addr.bdaddr, bdaddr);
6677 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6678 ev.passkey = __cpu_to_le32(passkey);
6679 ev.entered = entered;
6680
6681 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6682}
6683
Johan Hedberge1e930f2014-09-08 17:09:49 -07006684void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006685{
6686 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006687 struct pending_cmd *cmd;
6688 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006689
Johan Hedberge1e930f2014-09-08 17:09:49 -07006690 bacpy(&ev.addr.bdaddr, &conn->dst);
6691 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6692 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006693
Johan Hedberge1e930f2014-09-08 17:09:49 -07006694 cmd = find_pairing(conn);
6695
6696 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6697 cmd ? cmd->sk : NULL);
6698
6699 if (cmd)
6700 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006701}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006702
Marcel Holtmann464996a2013-10-15 14:26:24 -07006703void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006704{
6705 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006706 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006707
6708 if (status) {
6709 u8 mgmt_err = mgmt_status(status);
6710 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006711 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006712 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006713 }
6714
Marcel Holtmann464996a2013-10-15 14:26:24 -07006715 if (test_bit(HCI_AUTH, &hdev->flags))
6716 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6717 &hdev->dev_flags);
6718 else
6719 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6720 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006721
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006722 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006723 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006724
Johan Hedberg47990ea2012-02-22 11:58:37 +02006725 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006726 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006727
6728 if (match.sk)
6729 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006730}
6731
Johan Hedberg890ea892013-03-15 17:06:52 -05006732static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006733{
Johan Hedberg890ea892013-03-15 17:06:52 -05006734 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006735 struct hci_cp_write_eir cp;
6736
Johan Hedberg976eb202012-10-24 21:12:01 +03006737 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006738 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006739
Johan Hedbergc80da272012-02-22 15:38:48 +02006740 memset(hdev->eir, 0, sizeof(hdev->eir));
6741
Johan Hedbergcacaf522012-02-21 00:52:42 +02006742 memset(&cp, 0, sizeof(cp));
6743
Johan Hedberg890ea892013-03-15 17:06:52 -05006744 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006745}
6746
Marcel Holtmann3e248562013-10-15 14:26:25 -07006747void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006748{
6749 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006750 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006751 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006752
6753 if (status) {
6754 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006755
6756 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006757 &hdev->dev_flags)) {
6758 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006759 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006760 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006761
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006762 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6763 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006764 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006765 }
6766
6767 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006768 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006769 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006770 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6771 if (!changed)
6772 changed = test_and_clear_bit(HCI_HS_ENABLED,
6773 &hdev->dev_flags);
6774 else
6775 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006776 }
6777
6778 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6779
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006780 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006781 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006782
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006783 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006784 sock_put(match.sk);
6785
Johan Hedberg890ea892013-03-15 17:06:52 -05006786 hci_req_init(&req, hdev);
6787
Johan Hedberg37699722014-06-24 14:00:27 +03006788 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6789 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6790 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6791 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006792 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006793 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006794 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006795 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006796
6797 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006798}
6799
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006800void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6801{
6802 struct cmd_lookup match = { NULL, hdev };
6803 bool changed = false;
6804
6805 if (status) {
6806 u8 mgmt_err = mgmt_status(status);
6807
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006808 if (enable) {
6809 if (test_and_clear_bit(HCI_SC_ENABLED,
6810 &hdev->dev_flags))
6811 new_settings(hdev, NULL);
6812 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6813 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006814
6815 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6816 cmd_status_rsp, &mgmt_err);
6817 return;
6818 }
6819
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006820 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006821 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006822 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006823 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006824 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6825 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006826
6827 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6828 settings_rsp, &match);
6829
6830 if (changed)
6831 new_settings(hdev, match.sk);
6832
6833 if (match.sk)
6834 sock_put(match.sk);
6835}
6836
Johan Hedberg92da6092013-03-15 17:06:55 -05006837static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006838{
6839 struct cmd_lookup *match = data;
6840
Johan Hedberg90e70452012-02-23 23:09:40 +02006841 if (match->sk == NULL) {
6842 match->sk = cmd->sk;
6843 sock_hold(match->sk);
6844 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006845}
6846
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006847void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6848 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006849{
Johan Hedberg90e70452012-02-23 23:09:40 +02006850 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006851
Johan Hedberg92da6092013-03-15 17:06:55 -05006852 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6853 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6854 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006855
6856 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006857 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6858 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006859
6860 if (match.sk)
6861 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006862}
6863
Marcel Holtmann7667da32013-10-15 14:26:27 -07006864void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006865{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006866 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006867 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006868
Johan Hedberg13928972013-03-15 17:07:00 -05006869 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006870 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006871
6872 memset(&ev, 0, sizeof(ev));
6873 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006874 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006875
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006876 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006877 if (!cmd) {
6878 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006879
Johan Hedberg13928972013-03-15 17:07:00 -05006880 /* If this is a HCI command related to powering on the
6881 * HCI dev don't send any mgmt signals.
6882 */
6883 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006884 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006885 }
6886
Marcel Holtmann7667da32013-10-15 14:26:27 -07006887 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6888 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006889}
Szymon Jancc35938b2011-03-22 13:12:21 +01006890
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006891void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006892 u8 *rand192, u8 *hash256, u8 *rand256,
6893 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006894{
6895 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006896
Johan Hedberg744cf192011-11-08 20:40:14 +02006897 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006898
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006899 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006900 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006901 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006902
6903 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006904 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6905 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006906 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006907 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006908 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006909
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006910 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006911 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006912
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006913 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006914 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006915
6916 cmd_complete(cmd->sk, hdev->id,
6917 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6918 &rp, sizeof(rp));
6919 } else {
6920 struct mgmt_rp_read_local_oob_data rp;
6921
6922 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006923 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006924
6925 cmd_complete(cmd->sk, hdev->id,
6926 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6927 &rp, sizeof(rp));
6928 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006929 }
6930
6931 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006932}
Johan Hedberge17acd42011-03-30 23:57:16 +03006933
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006934/* this is reversed hex representation of bluetooth base uuid. We need it for
6935 * service uuid parsing in eir.
6936 */
6937static const u8 reverse_base_uuid[] = {
6938 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6939 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6940};
6941
6942static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6943{
6944 int i;
6945
6946 for (i = 0; i < uuid_count; i++) {
6947 if (!memcmp(uuid, uuids[i], 16))
6948 return true;
6949 }
6950
6951 return false;
6952}
6953
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006954static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6955{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006956 u16 parsed = 0;
6957
6958 while (parsed < eir_len) {
6959 u8 field_len = eir[0];
6960 u8 uuid[16];
6961 int i;
6962
6963 if (field_len == 0)
6964 break;
6965
6966 if (eir_len - parsed < field_len + 1)
6967 break;
6968
6969 switch (eir[1]) {
6970 case EIR_UUID16_ALL:
6971 case EIR_UUID16_SOME:
6972 for (i = 0; i + 3 <= field_len; i += 2) {
6973 memcpy(uuid, reverse_base_uuid, 16);
6974 uuid[13] = eir[i + 3];
6975 uuid[12] = eir[i + 2];
6976 if (has_uuid(uuid, uuid_count, uuids))
6977 return true;
6978 }
6979 break;
6980 case EIR_UUID32_ALL:
6981 case EIR_UUID32_SOME:
6982 for (i = 0; i + 5 <= field_len; i += 4) {
6983 memcpy(uuid, reverse_base_uuid, 16);
6984 uuid[15] = eir[i + 5];
6985 uuid[14] = eir[i + 4];
6986 uuid[13] = eir[i + 3];
6987 uuid[12] = eir[i + 2];
6988 if (has_uuid(uuid, uuid_count, uuids))
6989 return true;
6990 }
6991 break;
6992 case EIR_UUID128_ALL:
6993 case EIR_UUID128_SOME:
6994 for (i = 0; i + 17 <= field_len; i += 16) {
6995 memcpy(uuid, eir + i + 2, 16);
6996 if (has_uuid(uuid, uuid_count, uuids))
6997 return true;
6998 }
6999 break;
7000 }
7001
7002 parsed += field_len + 1;
7003 eir += field_len + 1;
7004 }
7005
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007006 return false;
7007}
7008
Marcel Holtmann901801b2013-10-06 23:55:51 -07007009void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007010 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7011 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007012{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007013 char buf[512];
7014 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007015 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007016 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007017
Johan Hedberg75ce2082014-07-02 22:42:01 +03007018 /* Don't send events for a non-kernel initiated discovery. With
7019 * LE one exception is if we have pend_le_reports > 0 in which
7020 * case we're doing passive scanning and want these events.
7021 */
7022 if (!hci_discovery_active(hdev)) {
7023 if (link_type == ACL_LINK)
7024 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007025 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007026 return;
7027 }
Andre Guedes12602d02013-04-30 15:29:40 -03007028
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007029 /* When using service discovery with a RSSI threshold, then check
7030 * if such a RSSI threshold is specified. If a RSSI threshold has
7031 * been specified, then all results with a RSSI smaller than the
7032 * RSSI threshold will be dropped.
7033 */
7034 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7035 rssi < hdev->discovery.rssi)
7036 return;
7037
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007038 /* Make sure that the buffer is big enough. The 5 extra bytes
7039 * are for the potential CoD field.
7040 */
7041 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007042 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007043
Johan Hedberg1dc06092012-01-15 21:01:23 +02007044 memset(buf, 0, sizeof(buf));
7045
Johan Hedberg841c5642014-07-07 12:45:54 +03007046 bacpy(&ev->addr.bdaddr, bdaddr);
7047 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007048 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007049 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007050
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007051 if (eir_len > 0) {
7052 /* When using service discovery and a list of UUID is
7053 * provided, results with no matching UUID should be
7054 * dropped. In case there is a match the result is
7055 * kept and checking possible scan response data
7056 * will be skipped.
7057 */
7058 if (hdev->discovery.uuid_count > 0) {
7059 match = eir_has_uuids(eir, eir_len,
7060 hdev->discovery.uuid_count,
7061 hdev->discovery.uuids);
7062 if (!match)
7063 return;
7064 }
7065
7066 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007067 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007068 } else {
7069 /* When using service discovery and a list of UUID is
7070 * provided, results with empty EIR or advertising data
7071 * should be dropped since they do not match any UUID.
7072 */
7073 if (hdev->discovery.uuid_count > 0)
7074 return;
7075 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007076
Johan Hedberg1dc06092012-01-15 21:01:23 +02007077 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7078 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007079 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007080
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007081 if (scan_rsp_len > 0) {
7082 /* When using service discovery and a list of UUID is
7083 * provided, results with no matching UUID should be
7084 * dropped if there is no previous match from the
7085 * advertising data.
7086 */
7087 if (hdev->discovery.uuid_count > 0) {
7088 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7089 hdev->discovery.uuid_count,
7090 hdev->discovery.uuids))
7091 return;
7092 }
7093
7094 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007095 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007096 } else {
7097 /* When using service discovery and a list of UUID is
7098 * provided, results with empty scan response and no
7099 * previous matched advertising data should be dropped.
7100 */
7101 if (hdev->discovery.uuid_count > 0 && !match)
7102 return;
7103 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007104
7105 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7106 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007107
Marcel Holtmann901801b2013-10-06 23:55:51 -07007108 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007109}
Johan Hedberga88a9652011-03-30 13:18:12 +03007110
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007111void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7112 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007113{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007114 struct mgmt_ev_device_found *ev;
7115 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7116 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007117
Johan Hedbergb644ba32012-01-17 21:48:47 +02007118 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007119
Johan Hedbergb644ba32012-01-17 21:48:47 +02007120 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007121
Johan Hedbergb644ba32012-01-17 21:48:47 +02007122 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007123 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007124 ev->rssi = rssi;
7125
7126 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007127 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007128
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007129 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007130
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007131 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007132}
Johan Hedberg314b2382011-04-27 10:29:57 -04007133
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007134void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007135{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007136 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007137
Andre Guedes343fb142011-11-22 17:14:19 -03007138 BT_DBG("%s discovering %u", hdev->name, discovering);
7139
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007140 memset(&ev, 0, sizeof(ev));
7141 ev.type = hdev->discovery.type;
7142 ev.discovering = discovering;
7143
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007144 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007145}
Antti Julku5e762442011-08-25 16:48:02 +03007146
Marcel Holtmann5976e602013-10-06 04:08:14 -07007147static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7148{
7149 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007150}
7151
7152void mgmt_reenable_advertising(struct hci_dev *hdev)
7153{
7154 struct hci_request req;
7155
Marcel Holtmann5976e602013-10-06 04:08:14 -07007156 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7157 return;
7158
7159 hci_req_init(&req, hdev);
7160 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007161 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007162}