blob: ec7c0ec3d8d3f12dd4dd2174d253a5ad02e17903 [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
Johan Hedberg0857dd32014-12-19 13:40:20 +020035#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070036#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020037
Johan Hedberg2da9c552012-02-17 14:39:28 +020038#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010039#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020040
Johan Hedberge70bb2e2012-02-13 16:59:33 +020041static const u16 mgmt_commands[] = {
42 MGMT_OP_READ_INDEX_LIST,
43 MGMT_OP_READ_INFO,
44 MGMT_OP_SET_POWERED,
45 MGMT_OP_SET_DISCOVERABLE,
46 MGMT_OP_SET_CONNECTABLE,
47 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030048 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020049 MGMT_OP_SET_LINK_SECURITY,
50 MGMT_OP_SET_SSP,
51 MGMT_OP_SET_HS,
52 MGMT_OP_SET_LE,
53 MGMT_OP_SET_DEV_CLASS,
54 MGMT_OP_SET_LOCAL_NAME,
55 MGMT_OP_ADD_UUID,
56 MGMT_OP_REMOVE_UUID,
57 MGMT_OP_LOAD_LINK_KEYS,
58 MGMT_OP_LOAD_LONG_TERM_KEYS,
59 MGMT_OP_DISCONNECT,
60 MGMT_OP_GET_CONNECTIONS,
61 MGMT_OP_PIN_CODE_REPLY,
62 MGMT_OP_PIN_CODE_NEG_REPLY,
63 MGMT_OP_SET_IO_CAPABILITY,
64 MGMT_OP_PAIR_DEVICE,
65 MGMT_OP_CANCEL_PAIR_DEVICE,
66 MGMT_OP_UNPAIR_DEVICE,
67 MGMT_OP_USER_CONFIRM_REPLY,
68 MGMT_OP_USER_CONFIRM_NEG_REPLY,
69 MGMT_OP_USER_PASSKEY_REPLY,
70 MGMT_OP_USER_PASSKEY_NEG_REPLY,
71 MGMT_OP_READ_LOCAL_OOB_DATA,
72 MGMT_OP_ADD_REMOTE_OOB_DATA,
73 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
74 MGMT_OP_START_DISCOVERY,
75 MGMT_OP_STOP_DISCOVERY,
76 MGMT_OP_CONFIRM_NAME,
77 MGMT_OP_BLOCK_DEVICE,
78 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070079 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030080 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030081 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070082 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070083 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080084 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080085 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020086 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020087 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020088 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030089 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020090 MGMT_OP_ADD_DEVICE,
91 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030092 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020093 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020094 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020095 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020096 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010097 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020098};
99
100static const u16 mgmt_events[] = {
101 MGMT_EV_CONTROLLER_ERROR,
102 MGMT_EV_INDEX_ADDED,
103 MGMT_EV_INDEX_REMOVED,
104 MGMT_EV_NEW_SETTINGS,
105 MGMT_EV_CLASS_OF_DEV_CHANGED,
106 MGMT_EV_LOCAL_NAME_CHANGED,
107 MGMT_EV_NEW_LINK_KEY,
108 MGMT_EV_NEW_LONG_TERM_KEY,
109 MGMT_EV_DEVICE_CONNECTED,
110 MGMT_EV_DEVICE_DISCONNECTED,
111 MGMT_EV_CONNECT_FAILED,
112 MGMT_EV_PIN_CODE_REQUEST,
113 MGMT_EV_USER_CONFIRM_REQUEST,
114 MGMT_EV_USER_PASSKEY_REQUEST,
115 MGMT_EV_AUTH_FAILED,
116 MGMT_EV_DEVICE_FOUND,
117 MGMT_EV_DISCOVERING,
118 MGMT_EV_DEVICE_BLOCKED,
119 MGMT_EV_DEVICE_UNBLOCKED,
120 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300121 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800122 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700123 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200124 MGMT_EV_DEVICE_ADDED,
125 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300126 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200127 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200128 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200129 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200130};
131
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800132#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200133
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200134struct pending_cmd {
135 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200136 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200137 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100138 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200139 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200140 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300141 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200142 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200143};
144
Johan Hedbergca69b792011-11-11 18:10:00 +0200145/* HCI to MGMT error code conversion table */
146static u8 mgmt_status_table[] = {
147 MGMT_STATUS_SUCCESS,
148 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
149 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
150 MGMT_STATUS_FAILED, /* Hardware Failure */
151 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
152 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200153 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200154 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
155 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
157 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
158 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
159 MGMT_STATUS_BUSY, /* Command Disallowed */
160 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
161 MGMT_STATUS_REJECTED, /* Rejected Security */
162 MGMT_STATUS_REJECTED, /* Rejected Personal */
163 MGMT_STATUS_TIMEOUT, /* Host Timeout */
164 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
165 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
166 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
167 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
168 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
169 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
170 MGMT_STATUS_BUSY, /* Repeated Attempts */
171 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
172 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
173 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
174 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
175 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
176 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
177 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
178 MGMT_STATUS_FAILED, /* Unspecified Error */
179 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
180 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
181 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
182 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
183 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
184 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
185 MGMT_STATUS_FAILED, /* Unit Link Key Used */
186 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
187 MGMT_STATUS_TIMEOUT, /* Instant Passed */
188 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
189 MGMT_STATUS_FAILED, /* Transaction Collision */
190 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
191 MGMT_STATUS_REJECTED, /* QoS Rejected */
192 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
193 MGMT_STATUS_REJECTED, /* Insufficient Security */
194 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
195 MGMT_STATUS_BUSY, /* Role Switch Pending */
196 MGMT_STATUS_FAILED, /* Slot Violation */
197 MGMT_STATUS_FAILED, /* Role Switch Failed */
198 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
199 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
200 MGMT_STATUS_BUSY, /* Host Busy Pairing */
201 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
202 MGMT_STATUS_BUSY, /* Controller Busy */
203 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
204 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
205 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
206 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
207 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
208};
209
210static u8 mgmt_status(u8 hci_status)
211{
212 if (hci_status < ARRAY_SIZE(mgmt_status_table))
213 return mgmt_status_table[hci_status];
214
215 return MGMT_STATUS_FAILED;
216}
217
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200218static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
219 struct sock *skip_sk)
220{
221 struct sk_buff *skb;
222 struct mgmt_hdr *hdr;
223
224 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
225 if (!skb)
226 return -ENOMEM;
227
228 hdr = (void *) skb_put(skb, sizeof(*hdr));
229 hdr->opcode = cpu_to_le16(event);
230 if (hdev)
231 hdr->index = cpu_to_le16(hdev->id);
232 else
233 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
234 hdr->len = cpu_to_le16(data_len);
235
236 if (data)
237 memcpy(skb_put(skb, data_len), data, data_len);
238
239 /* Time stamp */
240 __net_timestamp(skb);
241
242 hci_send_to_control(skb, skip_sk);
243 kfree_skb(skb);
244
245 return 0;
246}
247
Szymon Janc4e51eae2011-02-25 19:05:48 +0100248static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200249{
250 struct sk_buff *skb;
251 struct mgmt_hdr *hdr;
252 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300253 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200254
Szymon Janc34eb5252011-02-28 14:10:08 +0100255 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200256
Andre Guedes790eff42012-06-07 19:05:46 -0300257 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200258 if (!skb)
259 return -ENOMEM;
260
261 hdr = (void *) skb_put(skb, sizeof(*hdr));
262
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700263 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100264 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200265 hdr->len = cpu_to_le16(sizeof(*ev));
266
267 ev = (void *) skb_put(skb, sizeof(*ev));
268 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200269 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200270
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300271 err = sock_queue_rcv_skb(sk, skb);
272 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200273 kfree_skb(skb);
274
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300275 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200276}
277
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200278static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300279 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200280{
281 struct sk_buff *skb;
282 struct mgmt_hdr *hdr;
283 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300284 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200285
286 BT_DBG("sock %p", sk);
287
Andre Guedes790eff42012-06-07 19:05:46 -0300288 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200289 if (!skb)
290 return -ENOMEM;
291
292 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200293
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700294 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100295 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200296 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200297
Johan Hedberga38528f2011-01-22 06:46:43 +0200298 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200299 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200300 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100301
302 if (rp)
303 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200304
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300305 err = sock_queue_rcv_skb(sk, skb);
306 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200307 kfree_skb(skb);
308
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100309 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200310}
311
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300312static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
313 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200314{
315 struct mgmt_rp_read_version rp;
316
317 BT_DBG("sock %p", sk);
318
319 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700320 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200321
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200322 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300323 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200324}
325
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300326static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
327 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200328{
329 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200330 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
331 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200332 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200333 size_t rp_size;
334 int i, err;
335
336 BT_DBG("sock %p", sk);
337
338 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
339
340 rp = kmalloc(rp_size, GFP_KERNEL);
341 if (!rp)
342 return -ENOMEM;
343
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700344 rp->num_commands = cpu_to_le16(num_commands);
345 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200346
347 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
348 put_unaligned_le16(mgmt_commands[i], opcode);
349
350 for (i = 0; i < num_events; i++, opcode++)
351 put_unaligned_le16(mgmt_events[i], opcode);
352
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200353 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300354 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200355 kfree(rp);
356
357 return err;
358}
359
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300360static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
361 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200363 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200364 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200365 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200366 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300367 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200368
369 BT_DBG("sock %p", sk);
370
371 read_lock(&hci_dev_list_lock);
372
373 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300374 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200375 if (d->dev_type == HCI_BREDR &&
376 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700377 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200378 }
379
Johan Hedberga38528f2011-01-22 06:46:43 +0200380 rp_len = sizeof(*rp) + (2 * count);
381 rp = kmalloc(rp_len, GFP_ATOMIC);
382 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100383 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200384 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100385 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200386
Johan Hedberg476e44c2012-10-19 20:10:46 +0300387 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200388 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200389 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200390 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200391 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200392 continue;
393
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200394 /* Devices marked as raw-only are neither configured
395 * nor unconfigured controllers.
396 */
397 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700398 continue;
399
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200400 if (d->dev_type == HCI_BREDR &&
401 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700402 rp->index[count++] = cpu_to_le16(d->id);
403 BT_DBG("Added hci%u", d->id);
404 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200405 }
406
Johan Hedberg476e44c2012-10-19 20:10:46 +0300407 rp->num_controllers = cpu_to_le16(count);
408 rp_len = sizeof(*rp) + (2 * count);
409
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200410 read_unlock(&hci_dev_list_lock);
411
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200412 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300413 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200414
Johan Hedberga38528f2011-01-22 06:46:43 +0200415 kfree(rp);
416
417 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200418}
419
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200420static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
421 void *data, u16 data_len)
422{
423 struct mgmt_rp_read_unconf_index_list *rp;
424 struct hci_dev *d;
425 size_t rp_len;
426 u16 count;
427 int err;
428
429 BT_DBG("sock %p", sk);
430
431 read_lock(&hci_dev_list_lock);
432
433 count = 0;
434 list_for_each_entry(d, &hci_dev_list, list) {
435 if (d->dev_type == HCI_BREDR &&
436 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
437 count++;
438 }
439
440 rp_len = sizeof(*rp) + (2 * count);
441 rp = kmalloc(rp_len, GFP_ATOMIC);
442 if (!rp) {
443 read_unlock(&hci_dev_list_lock);
444 return -ENOMEM;
445 }
446
447 count = 0;
448 list_for_each_entry(d, &hci_dev_list, list) {
449 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200450 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200451 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
452 continue;
453
454 /* Devices marked as raw-only are neither configured
455 * nor unconfigured controllers.
456 */
457 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
458 continue;
459
460 if (d->dev_type == HCI_BREDR &&
461 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
462 rp->index[count++] = cpu_to_le16(d->id);
463 BT_DBG("Added hci%u", d->id);
464 }
465 }
466
467 rp->num_controllers = cpu_to_le16(count);
468 rp_len = sizeof(*rp) + (2 * count);
469
470 read_unlock(&hci_dev_list_lock);
471
472 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
473 0, rp, rp_len);
474
475 kfree(rp);
476
477 return err;
478}
479
Marcel Holtmanndbece372014-07-04 18:11:55 +0200480static bool is_configured(struct hci_dev *hdev)
481{
482 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
483 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
484 return false;
485
486 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
487 !bacmp(&hdev->public_addr, BDADDR_ANY))
488 return false;
489
490 return true;
491}
492
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200493static __le32 get_missing_options(struct hci_dev *hdev)
494{
495 u32 options = 0;
496
Marcel Holtmanndbece372014-07-04 18:11:55 +0200497 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
498 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200499 options |= MGMT_OPTION_EXTERNAL_CONFIG;
500
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200501 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
502 !bacmp(&hdev->public_addr, BDADDR_ANY))
503 options |= MGMT_OPTION_PUBLIC_ADDRESS;
504
505 return cpu_to_le32(options);
506}
507
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200508static int new_options(struct hci_dev *hdev, struct sock *skip)
509{
510 __le32 options = get_missing_options(hdev);
511
512 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
513 sizeof(options), skip);
514}
515
Marcel Holtmanndbece372014-07-04 18:11:55 +0200516static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
517{
518 __le32 options = get_missing_options(hdev);
519
520 return cmd_complete(sk, hdev->id, opcode, 0, &options,
521 sizeof(options));
522}
523
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200524static int read_config_info(struct sock *sk, struct hci_dev *hdev,
525 void *data, u16 data_len)
526{
527 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200528 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200529
530 BT_DBG("sock %p %s", sk, hdev->name);
531
532 hci_dev_lock(hdev);
533
534 memset(&rp, 0, sizeof(rp));
535 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200536
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200537 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
538 options |= MGMT_OPTION_EXTERNAL_CONFIG;
539
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200540 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200541 options |= MGMT_OPTION_PUBLIC_ADDRESS;
542
543 rp.supported_options = cpu_to_le32(options);
544 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200545
546 hci_dev_unlock(hdev);
547
548 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
549 sizeof(rp));
550}
551
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200552static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200553{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200554 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200555
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200556 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300557 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800558 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300559 settings |= MGMT_SETTING_CONNECTABLE;
560 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200561
Andre Guedesed3fa312012-07-24 15:03:46 -0300562 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500563 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
564 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200565 settings |= MGMT_SETTING_BREDR;
566 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700567
568 if (lmp_ssp_capable(hdev)) {
569 settings |= MGMT_SETTING_SSP;
570 settings |= MGMT_SETTING_HS;
571 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800572
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800573 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200574 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800575 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700576 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100577
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300578 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200579 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300580 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300581 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200582 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300583 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200584
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200585 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
586 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200587 settings |= MGMT_SETTING_CONFIGURATION;
588
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200589 return settings;
590}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200591
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200592static u32 get_current_settings(struct hci_dev *hdev)
593{
594 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200595
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200596 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100597 settings |= MGMT_SETTING_POWERED;
598
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200599 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200600 settings |= MGMT_SETTING_CONNECTABLE;
601
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500602 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
603 settings |= MGMT_SETTING_FAST_CONNECTABLE;
604
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200605 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200606 settings |= MGMT_SETTING_DISCOVERABLE;
607
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300608 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300609 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200610
Johan Hedberg56f87902013-10-02 13:43:13 +0300611 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200612 settings |= MGMT_SETTING_BREDR;
613
Johan Hedberg06199cf2012-02-22 16:37:11 +0200614 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200615 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200616
Johan Hedberg47990ea2012-02-22 11:58:37 +0200617 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200618 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200619
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200620 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200621 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200622
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200623 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
624 settings |= MGMT_SETTING_HS;
625
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200626 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300627 settings |= MGMT_SETTING_ADVERTISING;
628
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800629 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
630 settings |= MGMT_SETTING_SECURE_CONN;
631
Johan Hedberg0663b292014-06-24 13:15:50 +0300632 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800633 settings |= MGMT_SETTING_DEBUG_KEYS;
634
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200635 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
636 settings |= MGMT_SETTING_PRIVACY;
637
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200638 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200639}
640
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300641#define PNP_INFO_SVCLASS_ID 0x1200
642
Johan Hedberg213202e2013-01-27 00:31:33 +0200643static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
644{
645 u8 *ptr = data, *uuids_start = NULL;
646 struct bt_uuid *uuid;
647
648 if (len < 4)
649 return ptr;
650
651 list_for_each_entry(uuid, &hdev->uuids, list) {
652 u16 uuid16;
653
654 if (uuid->size != 16)
655 continue;
656
657 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
658 if (uuid16 < 0x1100)
659 continue;
660
661 if (uuid16 == PNP_INFO_SVCLASS_ID)
662 continue;
663
664 if (!uuids_start) {
665 uuids_start = ptr;
666 uuids_start[0] = 1;
667 uuids_start[1] = EIR_UUID16_ALL;
668 ptr += 2;
669 }
670
671 /* Stop if not enough space to put next UUID */
672 if ((ptr - data) + sizeof(u16) > len) {
673 uuids_start[1] = EIR_UUID16_SOME;
674 break;
675 }
676
677 *ptr++ = (uuid16 & 0x00ff);
678 *ptr++ = (uuid16 & 0xff00) >> 8;
679 uuids_start[0] += sizeof(uuid16);
680 }
681
682 return ptr;
683}
684
Johan Hedbergcdf19632013-01-27 00:31:34 +0200685static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
686{
687 u8 *ptr = data, *uuids_start = NULL;
688 struct bt_uuid *uuid;
689
690 if (len < 6)
691 return ptr;
692
693 list_for_each_entry(uuid, &hdev->uuids, list) {
694 if (uuid->size != 32)
695 continue;
696
697 if (!uuids_start) {
698 uuids_start = ptr;
699 uuids_start[0] = 1;
700 uuids_start[1] = EIR_UUID32_ALL;
701 ptr += 2;
702 }
703
704 /* Stop if not enough space to put next UUID */
705 if ((ptr - data) + sizeof(u32) > len) {
706 uuids_start[1] = EIR_UUID32_SOME;
707 break;
708 }
709
710 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
711 ptr += sizeof(u32);
712 uuids_start[0] += sizeof(u32);
713 }
714
715 return ptr;
716}
717
Johan Hedbergc00d5752013-01-27 00:31:35 +0200718static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
719{
720 u8 *ptr = data, *uuids_start = NULL;
721 struct bt_uuid *uuid;
722
723 if (len < 18)
724 return ptr;
725
726 list_for_each_entry(uuid, &hdev->uuids, list) {
727 if (uuid->size != 128)
728 continue;
729
730 if (!uuids_start) {
731 uuids_start = ptr;
732 uuids_start[0] = 1;
733 uuids_start[1] = EIR_UUID128_ALL;
734 ptr += 2;
735 }
736
737 /* Stop if not enough space to put next UUID */
738 if ((ptr - data) + 16 > len) {
739 uuids_start[1] = EIR_UUID128_SOME;
740 break;
741 }
742
743 memcpy(ptr, uuid->uuid, 16);
744 ptr += 16;
745 uuids_start[0] += 16;
746 }
747
748 return ptr;
749}
750
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300751static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
752{
753 struct pending_cmd *cmd;
754
755 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
756 if (cmd->opcode == opcode)
757 return cmd;
758 }
759
760 return NULL;
761}
762
Johan Hedberg95868422014-06-28 17:54:07 +0300763static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
764 struct hci_dev *hdev,
765 const void *data)
766{
767 struct pending_cmd *cmd;
768
769 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
770 if (cmd->user_data != data)
771 continue;
772 if (cmd->opcode == opcode)
773 return cmd;
774 }
775
776 return NULL;
777}
778
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700779static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
780{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700781 u8 ad_len = 0;
782 size_t name_len;
783
784 name_len = strlen(hdev->dev_name);
785 if (name_len > 0) {
786 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
787
788 if (name_len > max_len) {
789 name_len = max_len;
790 ptr[1] = EIR_NAME_SHORT;
791 } else
792 ptr[1] = EIR_NAME_COMPLETE;
793
794 ptr[0] = name_len + 1;
795
796 memcpy(ptr + 2, hdev->dev_name, name_len);
797
798 ad_len += (name_len + 2);
799 ptr += (name_len + 2);
800 }
801
802 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700803}
804
805static void update_scan_rsp_data(struct hci_request *req)
806{
807 struct hci_dev *hdev = req->hdev;
808 struct hci_cp_le_set_scan_rsp_data cp;
809 u8 len;
810
Johan Hedberg7751ef12013-10-19 23:38:15 +0300811 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700812 return;
813
814 memset(&cp, 0, sizeof(cp));
815
816 len = create_scan_rsp_data(hdev, cp.data);
817
Johan Hedbergeb438b52013-10-16 15:31:07 +0300818 if (hdev->scan_rsp_data_len == len &&
819 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700820 return;
821
Johan Hedbergeb438b52013-10-16 15:31:07 +0300822 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
823 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700824
825 cp.length = len;
826
827 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
828}
829
Johan Hedberg9a43e252013-10-20 19:00:07 +0300830static u8 get_adv_discov_flags(struct hci_dev *hdev)
831{
832 struct pending_cmd *cmd;
833
834 /* If there's a pending mgmt command the flags will not yet have
835 * their final values, so check for this first.
836 */
837 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
838 if (cmd) {
839 struct mgmt_mode *cp = cmd->param;
840 if (cp->val == 0x01)
841 return LE_AD_GENERAL;
842 else if (cp->val == 0x02)
843 return LE_AD_LIMITED;
844 } else {
845 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
846 return LE_AD_LIMITED;
847 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
848 return LE_AD_GENERAL;
849 }
850
851 return 0;
852}
853
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700854static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700855{
856 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700857
Johan Hedberg9a43e252013-10-20 19:00:07 +0300858 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700859
Johan Hedberge8340042014-01-30 11:16:50 -0800860 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700862
863 if (flags) {
864 BT_DBG("adv flags 0x%02x", flags);
865
866 ptr[0] = 2;
867 ptr[1] = EIR_FLAGS;
868 ptr[2] = flags;
869
870 ad_len += 3;
871 ptr += 3;
872 }
873
874 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
875 ptr[0] = 2;
876 ptr[1] = EIR_TX_POWER;
877 ptr[2] = (u8) hdev->adv_tx_power;
878
879 ad_len += 3;
880 ptr += 3;
881 }
882
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700883 return ad_len;
884}
885
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700886static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700887{
888 struct hci_dev *hdev = req->hdev;
889 struct hci_cp_le_set_adv_data cp;
890 u8 len;
891
Johan Hedberg10994ce2013-10-19 23:38:16 +0300892 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700893 return;
894
895 memset(&cp, 0, sizeof(cp));
896
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700897 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700898
899 if (hdev->adv_data_len == len &&
900 memcmp(cp.data, hdev->adv_data, len) == 0)
901 return;
902
903 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
904 hdev->adv_data_len = len;
905
906 cp.length = len;
907
908 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
909}
910
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300911int mgmt_update_adv_data(struct hci_dev *hdev)
912{
913 struct hci_request req;
914
915 hci_req_init(&req, hdev);
916 update_adv_data(&req);
917
918 return hci_req_run(&req, NULL);
919}
920
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300921static void create_eir(struct hci_dev *hdev, u8 *data)
922{
923 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300924 size_t name_len;
925
926 name_len = strlen(hdev->dev_name);
927
928 if (name_len > 0) {
929 /* EIR Data type */
930 if (name_len > 48) {
931 name_len = 48;
932 ptr[1] = EIR_NAME_SHORT;
933 } else
934 ptr[1] = EIR_NAME_COMPLETE;
935
936 /* EIR Data length */
937 ptr[0] = name_len + 1;
938
939 memcpy(ptr + 2, hdev->dev_name, name_len);
940
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300941 ptr += (name_len + 2);
942 }
943
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100944 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700945 ptr[0] = 2;
946 ptr[1] = EIR_TX_POWER;
947 ptr[2] = (u8) hdev->inq_tx_power;
948
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700949 ptr += 3;
950 }
951
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700952 if (hdev->devid_source > 0) {
953 ptr[0] = 9;
954 ptr[1] = EIR_DEVICE_ID;
955
956 put_unaligned_le16(hdev->devid_source, ptr + 2);
957 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
958 put_unaligned_le16(hdev->devid_product, ptr + 6);
959 put_unaligned_le16(hdev->devid_version, ptr + 8);
960
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700961 ptr += 10;
962 }
963
Johan Hedberg213202e2013-01-27 00:31:33 +0200964 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200965 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200966 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300967}
968
Johan Hedberg890ea892013-03-15 17:06:52 -0500969static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300970{
Johan Hedberg890ea892013-03-15 17:06:52 -0500971 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300972 struct hci_cp_write_eir cp;
973
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200974 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500975 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200976
Johan Hedberg976eb202012-10-24 21:12:01 +0300977 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500978 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300979
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200980 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500981 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300982
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200983 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500984 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300985
986 memset(&cp, 0, sizeof(cp));
987
988 create_eir(hdev, cp.data);
989
990 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500991 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300992
993 memcpy(hdev->eir, cp.data, sizeof(cp.data));
994
Johan Hedberg890ea892013-03-15 17:06:52 -0500995 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300996}
997
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200998static u8 get_service_classes(struct hci_dev *hdev)
999{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001000 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001001 u8 val = 0;
1002
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001003 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001005
1006 return val;
1007}
1008
Johan Hedberg890ea892013-03-15 17:06:52 -05001009static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001010{
Johan Hedberg890ea892013-03-15 17:06:52 -05001011 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001012 u8 cod[3];
1013
1014 BT_DBG("%s", hdev->name);
1015
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001016 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001017 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001018
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001019 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1020 return;
1021
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001022 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001023 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001024
1025 cod[0] = hdev->minor_class;
1026 cod[1] = hdev->major_class;
1027 cod[2] = get_service_classes(hdev);
1028
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001029 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1030 cod[1] |= 0x20;
1031
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001032 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001033 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001034
Johan Hedberg890ea892013-03-15 17:06:52 -05001035 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001036}
1037
Johan Hedberga4858cb2014-02-25 19:56:31 +02001038static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001039{
1040 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001041
1042 /* If there's a pending mgmt command the flag will not yet have
1043 * it's final value, so check for this first.
1044 */
1045 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1046 if (cmd) {
1047 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001048 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001049 }
1050
Johan Hedberga4858cb2014-02-25 19:56:31 +02001051 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001052}
1053
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001054static void disable_advertising(struct hci_request *req)
1055{
1056 u8 enable = 0x00;
1057
1058 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1059}
1060
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001061static void enable_advertising(struct hci_request *req)
1062{
1063 struct hci_dev *hdev = req->hdev;
1064 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001065 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001066 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001067
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001068 if (hci_conn_num(hdev, LE_LINK) > 0)
1069 return;
1070
1071 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1072 disable_advertising(req);
1073
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001074 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001075 * hci_update_random_address knows that it's safe to go ahead
1076 * and write a new random address. The flag will be set back on
1077 * as soon as the SET_ADV_ENABLE HCI command completes.
1078 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001079 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001080
Johan Hedberga4858cb2014-02-25 19:56:31 +02001081 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001082
Johan Hedberga4858cb2014-02-25 19:56:31 +02001083 /* Set require_privacy to true only when non-connectable
1084 * advertising is used. In that case it is fine to use a
1085 * non-resolvable private address.
1086 */
1087 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001088 return;
1089
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001090 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001091 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1092 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001093 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001094 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001095 cp.channel_map = hdev->le_adv_channel_map;
1096
1097 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1098
1099 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1100}
1101
Johan Hedberg7d785252011-12-15 00:47:39 +02001102static void service_cache_off(struct work_struct *work)
1103{
1104 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001105 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001106 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001107
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001108 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001109 return;
1110
Johan Hedberg890ea892013-03-15 17:06:52 -05001111 hci_req_init(&req, hdev);
1112
Johan Hedberg7d785252011-12-15 00:47:39 +02001113 hci_dev_lock(hdev);
1114
Johan Hedberg890ea892013-03-15 17:06:52 -05001115 update_eir(&req);
1116 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001117
1118 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001119
1120 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001121}
1122
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001123static void rpa_expired(struct work_struct *work)
1124{
1125 struct hci_dev *hdev = container_of(work, struct hci_dev,
1126 rpa_expired.work);
1127 struct hci_request req;
1128
1129 BT_DBG("");
1130
1131 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1132
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001133 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001134 return;
1135
1136 /* The generation of a new RPA and programming it into the
1137 * controller happens in the enable_advertising() function.
1138 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001141 hci_req_run(&req, NULL);
1142}
1143
Johan Hedberg6a919082012-02-28 06:17:26 +02001144static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001145{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001146 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001147 return;
1148
Johan Hedberg4f87da82012-03-02 19:55:56 +02001149 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001150 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001151
Johan Hedberg4f87da82012-03-02 19:55:56 +02001152 /* Non-mgmt controlled devices get this bit set
1153 * implicitly so that pairing works for them, however
1154 * for mgmt we require user-space to explicitly enable
1155 * it
1156 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001157 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001158}
1159
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001160static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001161 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001162{
1163 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001164
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001165 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001166
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001167 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001168
Johan Hedberg03811012010-12-08 00:21:06 +02001169 memset(&rp, 0, sizeof(rp));
1170
Johan Hedberg03811012010-12-08 00:21:06 +02001171 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001172
1173 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001174 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001175
1176 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1177 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1178
1179 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001180
1181 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001182 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001183
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001184 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001185
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001186 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001187 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001188}
1189
1190static void mgmt_pending_free(struct pending_cmd *cmd)
1191{
1192 sock_put(cmd->sk);
1193 kfree(cmd->param);
1194 kfree(cmd);
1195}
1196
1197static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001198 struct hci_dev *hdev, void *data,
1199 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001200{
1201 struct pending_cmd *cmd;
1202
Johan Hedbergfca20012014-06-28 17:54:05 +03001203 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001204 if (!cmd)
1205 return NULL;
1206
1207 cmd->opcode = opcode;
1208 cmd->index = hdev->id;
1209
Johan Hedberg323b0b82014-12-05 13:36:01 +02001210 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001211 if (!cmd->param) {
1212 kfree(cmd);
1213 return NULL;
1214 }
1215
Johan Hedberg323b0b82014-12-05 13:36:01 +02001216 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001217
1218 cmd->sk = sk;
1219 sock_hold(sk);
1220
1221 list_add(&cmd->list, &hdev->mgmt_pending);
1222
1223 return cmd;
1224}
1225
1226static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001227 void (*cb)(struct pending_cmd *cmd,
1228 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001229 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001230{
Andre Guedesa3d09352013-02-01 11:21:30 -03001231 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001232
Andre Guedesa3d09352013-02-01 11:21:30 -03001233 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001234 if (opcode > 0 && cmd->opcode != opcode)
1235 continue;
1236
1237 cb(cmd, data);
1238 }
1239}
1240
Johan Hedberg03811012010-12-08 00:21:06 +02001241static void mgmt_pending_remove(struct pending_cmd *cmd)
1242{
1243 list_del(&cmd->list);
1244 mgmt_pending_free(cmd);
1245}
1246
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001247static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001248{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001249 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001250
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001251 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001252 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001253}
1254
Johan Hedberg8b064a32014-02-24 14:52:22 +02001255static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1256{
1257 BT_DBG("%s status 0x%02x", hdev->name, status);
1258
Johan Hedberga3172b72014-02-28 09:33:44 +02001259 if (hci_conn_count(hdev) == 0) {
1260 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001261 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001262 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001263}
1264
Johan Hedberg23a48092014-07-08 16:05:06 +03001265static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001266{
1267 struct hci_dev *hdev = req->hdev;
1268 struct hci_cp_remote_name_req_cancel cp;
1269 struct inquiry_entry *e;
1270
1271 switch (hdev->discovery.state) {
1272 case DISCOVERY_FINDING:
1273 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1274 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1275 } else {
1276 cancel_delayed_work(&hdev->le_scan_disable);
1277 hci_req_add_le_scan_disable(req);
1278 }
1279
Johan Hedberg23a48092014-07-08 16:05:06 +03001280 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001281
1282 case DISCOVERY_RESOLVING:
1283 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1284 NAME_PENDING);
1285 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001286 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001287
1288 bacpy(&cp.bdaddr, &e->data.bdaddr);
1289 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1290 &cp);
1291
Johan Hedberg23a48092014-07-08 16:05:06 +03001292 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001293
1294 default:
1295 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001296 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001297 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001298 return true;
1299 }
1300
Johan Hedberg21a60d32014-06-10 14:05:58 +03001301 break;
1302 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001303
1304 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001305}
1306
Johan Hedberg8b064a32014-02-24 14:52:22 +02001307static int clean_up_hci_state(struct hci_dev *hdev)
1308{
1309 struct hci_request req;
1310 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001311 bool discov_stopped;
1312 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001313
1314 hci_req_init(&req, hdev);
1315
1316 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1317 test_bit(HCI_PSCAN, &hdev->flags)) {
1318 u8 scan = 0x00;
1319 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1320 }
1321
Johan Hedberg73e082f2014-07-08 15:07:51 +03001322 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001323 disable_advertising(&req);
1324
Johan Hedberg23a48092014-07-08 16:05:06 +03001325 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001326
1327 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1328 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001329 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001330
Johan Hedbergc9910d02014-02-27 14:35:12 +02001331 switch (conn->state) {
1332 case BT_CONNECTED:
1333 case BT_CONFIG:
1334 dc.handle = cpu_to_le16(conn->handle);
1335 dc.reason = 0x15; /* Terminated due to Power Off */
1336 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1337 break;
1338 case BT_CONNECT:
1339 if (conn->type == LE_LINK)
1340 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1341 0, NULL);
1342 else if (conn->type == ACL_LINK)
1343 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1344 6, &conn->dst);
1345 break;
1346 case BT_CONNECT2:
1347 bacpy(&rej.bdaddr, &conn->dst);
1348 rej.reason = 0x15; /* Terminated due to Power Off */
1349 if (conn->type == ACL_LINK)
1350 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1351 sizeof(rej), &rej);
1352 else if (conn->type == SCO_LINK)
1353 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1354 sizeof(rej), &rej);
1355 break;
1356 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001357 }
1358
Johan Hedberg23a48092014-07-08 16:05:06 +03001359 err = hci_req_run(&req, clean_up_hci_complete);
1360 if (!err && discov_stopped)
1361 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1362
1363 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001364}
1365
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001366static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001367 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001368{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001369 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001370 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001371 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001372
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001373 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001374
Johan Hedberga7e80f22013-01-09 16:05:19 +02001375 if (cp->val != 0x00 && cp->val != 0x01)
1376 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1377 MGMT_STATUS_INVALID_PARAMS);
1378
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001379 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001380
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001381 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1382 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1383 MGMT_STATUS_BUSY);
1384 goto failed;
1385 }
1386
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001387 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1388 cancel_delayed_work(&hdev->power_off);
1389
1390 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001391 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1392 data, len);
1393 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001394 goto failed;
1395 }
1396 }
1397
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001398 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001399 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001400 goto failed;
1401 }
1402
Johan Hedberg03811012010-12-08 00:21:06 +02001403 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1404 if (!cmd) {
1405 err = -ENOMEM;
1406 goto failed;
1407 }
1408
Johan Hedberg8b064a32014-02-24 14:52:22 +02001409 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001410 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001411 err = 0;
1412 } else {
1413 /* Disconnect connections, stop scans, etc */
1414 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001415 if (!err)
1416 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1417 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001418
Johan Hedberg8b064a32014-02-24 14:52:22 +02001419 /* ENODATA means there were no HCI commands queued */
1420 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001421 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001422 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1423 err = 0;
1424 }
1425 }
Johan Hedberg03811012010-12-08 00:21:06 +02001426
1427failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001428 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001429 return err;
1430}
1431
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001432static int new_settings(struct hci_dev *hdev, struct sock *skip)
1433{
1434 __le32 ev;
1435
1436 ev = cpu_to_le32(get_current_settings(hdev));
1437
1438 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1439}
1440
Johan Hedberg91a668b2014-07-09 13:28:26 +03001441int mgmt_new_settings(struct hci_dev *hdev)
1442{
1443 return new_settings(hdev, NULL);
1444}
1445
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001446struct cmd_lookup {
1447 struct sock *sk;
1448 struct hci_dev *hdev;
1449 u8 mgmt_status;
1450};
1451
1452static void settings_rsp(struct pending_cmd *cmd, void *data)
1453{
1454 struct cmd_lookup *match = data;
1455
1456 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1457
1458 list_del(&cmd->list);
1459
1460 if (match->sk == NULL) {
1461 match->sk = cmd->sk;
1462 sock_hold(match->sk);
1463 }
1464
1465 mgmt_pending_free(cmd);
1466}
1467
1468static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1469{
1470 u8 *status = data;
1471
1472 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1473 mgmt_pending_remove(cmd);
1474}
1475
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001476static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1477{
1478 if (cmd->cmd_complete) {
1479 u8 *status = data;
1480
1481 cmd->cmd_complete(cmd, *status);
1482 mgmt_pending_remove(cmd);
1483
1484 return;
1485 }
1486
1487 cmd_status_rsp(cmd, data);
1488}
1489
Johan Hedbergf5818c22014-12-05 13:36:02 +02001490static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
1491{
1492 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1493 cmd->param_len);
1494}
1495
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001496static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1497{
1498 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1499 sizeof(struct mgmt_addr_info));
1500}
1501
Johan Hedberge6fe7982013-10-02 15:45:22 +03001502static u8 mgmt_bredr_support(struct hci_dev *hdev)
1503{
1504 if (!lmp_bredr_capable(hdev))
1505 return MGMT_STATUS_NOT_SUPPORTED;
1506 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1507 return MGMT_STATUS_REJECTED;
1508 else
1509 return MGMT_STATUS_SUCCESS;
1510}
1511
1512static u8 mgmt_le_support(struct hci_dev *hdev)
1513{
1514 if (!lmp_le_capable(hdev))
1515 return MGMT_STATUS_NOT_SUPPORTED;
1516 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1517 return MGMT_STATUS_REJECTED;
1518 else
1519 return MGMT_STATUS_SUCCESS;
1520}
1521
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001522static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1523{
1524 struct pending_cmd *cmd;
1525 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001526 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001527 bool changed;
1528
1529 BT_DBG("status 0x%02x", status);
1530
1531 hci_dev_lock(hdev);
1532
1533 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1534 if (!cmd)
1535 goto unlock;
1536
1537 if (status) {
1538 u8 mgmt_err = mgmt_status(status);
1539 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001540 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001541 goto remove_cmd;
1542 }
1543
1544 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001545 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001546 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1547 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001548
1549 if (hdev->discov_timeout > 0) {
1550 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1551 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1552 to);
1553 }
1554 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001555 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1556 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001557 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001558
1559 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1560
1561 if (changed)
1562 new_settings(hdev, cmd->sk);
1563
Marcel Holtmann970ba522013-10-15 06:33:57 -07001564 /* When the discoverable mode gets changed, make sure
1565 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001566 * bit correctly set. Also update page scan based on whitelist
1567 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001568 */
1569 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001570 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001571 update_class(&req);
1572 hci_req_run(&req, NULL);
1573
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001574remove_cmd:
1575 mgmt_pending_remove(cmd);
1576
1577unlock:
1578 hci_dev_unlock(hdev);
1579}
1580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001581static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001582 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001584 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001585 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001586 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001587 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001588 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001589 int err;
1590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001591 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001592
Johan Hedberg9a43e252013-10-20 19:00:07 +03001593 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1594 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001595 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001596 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001597
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001598 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001599 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1600 MGMT_STATUS_INVALID_PARAMS);
1601
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001602 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001603
1604 /* Disabling discoverable requires that no timeout is set,
1605 * and enabling limited discoverable requires a timeout.
1606 */
1607 if ((cp->val == 0x00 && timeout > 0) ||
1608 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001609 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001610 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001611
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001612 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001613
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001614 if (!hdev_is_powered(hdev) && timeout > 0) {
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_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001617 goto failed;
1618 }
1619
1620 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001621 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001622 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001623 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001624 goto failed;
1625 }
1626
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001627 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001628 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001629 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001630 goto failed;
1631 }
1632
1633 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001634 bool changed = false;
1635
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001636 /* Setting limited discoverable when powered off is
1637 * not a valid operation since it requires a timeout
1638 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1639 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001640 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1641 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1642 changed = true;
1643 }
1644
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001645 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001646 if (err < 0)
1647 goto failed;
1648
1649 if (changed)
1650 err = new_settings(hdev, sk);
1651
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001652 goto failed;
1653 }
1654
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001655 /* If the current mode is the same, then just update the timeout
1656 * value with the new value. And if only the timeout gets updated,
1657 * then no need for any HCI transactions.
1658 */
1659 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1660 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1661 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001662 cancel_delayed_work(&hdev->discov_off);
1663 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001664
Marcel Holtmann36261542013-10-15 08:28:51 -07001665 if (cp->val && hdev->discov_timeout > 0) {
1666 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001667 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001668 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001669 }
1670
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001671 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001672 goto failed;
1673 }
1674
1675 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1676 if (!cmd) {
1677 err = -ENOMEM;
1678 goto failed;
1679 }
1680
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001681 /* Cancel any potential discoverable timeout that might be
1682 * still active and store new timeout value. The arming of
1683 * the timeout happens in the complete handler.
1684 */
1685 cancel_delayed_work(&hdev->discov_off);
1686 hdev->discov_timeout = timeout;
1687
Johan Hedbergb456f872013-10-19 23:38:22 +03001688 /* Limited discoverable mode */
1689 if (cp->val == 0x02)
1690 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1691 else
1692 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1693
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001694 hci_req_init(&req, hdev);
1695
Johan Hedberg9a43e252013-10-20 19:00:07 +03001696 /* The procedure for LE-only controllers is much simpler - just
1697 * update the advertising data.
1698 */
1699 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1700 goto update_ad;
1701
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001702 scan = SCAN_PAGE;
1703
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001704 if (cp->val) {
1705 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001706
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001707 if (cp->val == 0x02) {
1708 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001709 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001710 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1711 hci_cp.iac_lap[1] = 0x8b;
1712 hci_cp.iac_lap[2] = 0x9e;
1713 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1714 hci_cp.iac_lap[4] = 0x8b;
1715 hci_cp.iac_lap[5] = 0x9e;
1716 } else {
1717 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001718 hci_cp.num_iac = 1;
1719 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1720 hci_cp.iac_lap[1] = 0x8b;
1721 hci_cp.iac_lap[2] = 0x9e;
1722 }
1723
1724 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1725 (hci_cp.num_iac * 3) + 1, &hci_cp);
1726
1727 scan |= SCAN_INQUIRY;
1728 } else {
1729 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1730 }
1731
1732 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001733
Johan Hedberg9a43e252013-10-20 19:00:07 +03001734update_ad:
1735 update_adv_data(&req);
1736
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001738 if (err < 0)
1739 mgmt_pending_remove(cmd);
1740
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001741failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001742 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001743 return err;
1744}
1745
Johan Hedberg406d7802013-03-15 17:07:09 -05001746static void write_fast_connectable(struct hci_request *req, bool enable)
1747{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001748 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001749 struct hci_cp_write_page_scan_activity acp;
1750 u8 type;
1751
Johan Hedberg547003b2013-10-21 16:51:53 +03001752 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1753 return;
1754
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001755 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1756 return;
1757
Johan Hedberg406d7802013-03-15 17:07:09 -05001758 if (enable) {
1759 type = PAGE_SCAN_TYPE_INTERLACED;
1760
1761 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001762 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001763 } else {
1764 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1765
1766 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001767 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001768 }
1769
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001770 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001771
Johan Hedbergbd98b992013-03-15 17:07:13 -05001772 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1773 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1774 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1775 sizeof(acp), &acp);
1776
1777 if (hdev->page_scan_type != type)
1778 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001779}
1780
Johan Hedberg2b76f452013-03-15 17:07:04 -05001781static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1782{
1783 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001784 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001785 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001786
1787 BT_DBG("status 0x%02x", status);
1788
1789 hci_dev_lock(hdev);
1790
1791 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1792 if (!cmd)
1793 goto unlock;
1794
Johan Hedberg37438c12013-10-14 16:20:05 +03001795 if (status) {
1796 u8 mgmt_err = mgmt_status(status);
1797 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1798 goto remove_cmd;
1799 }
1800
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001801 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001802 if (cp->val) {
1803 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1804 &hdev->dev_flags);
1805 discov_changed = false;
1806 } else {
1807 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1808 &hdev->dev_flags);
1809 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1810 &hdev->dev_flags);
1811 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001812
Johan Hedberg2b76f452013-03-15 17:07:04 -05001813 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1814
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001815 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001816 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001817 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001818 if (discov_changed)
1819 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001820 hci_update_background_scan(hdev);
1821 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001822
Johan Hedberg37438c12013-10-14 16:20:05 +03001823remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001824 mgmt_pending_remove(cmd);
1825
1826unlock:
1827 hci_dev_unlock(hdev);
1828}
1829
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001830static int set_connectable_update_settings(struct hci_dev *hdev,
1831 struct sock *sk, u8 val)
1832{
1833 bool changed = false;
1834 int err;
1835
1836 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1837 changed = true;
1838
1839 if (val) {
1840 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1841 } else {
1842 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1843 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1844 }
1845
1846 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1847 if (err < 0)
1848 return err;
1849
Johan Hedberg562064e2014-07-08 16:35:34 +03001850 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001851 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001852 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001853 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001854 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001855
1856 return 0;
1857}
1858
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001859static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001860 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001861{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001862 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001863 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001864 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001865 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001866 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001867
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001868 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001869
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001870 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1871 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001872 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001873 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001874
Johan Hedberga7e80f22013-01-09 16:05:19 +02001875 if (cp->val != 0x00 && cp->val != 0x01)
1876 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1877 MGMT_STATUS_INVALID_PARAMS);
1878
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001879 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001880
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001881 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001882 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001883 goto failed;
1884 }
1885
1886 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001887 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001888 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001889 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001890 goto failed;
1891 }
1892
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001893 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1894 if (!cmd) {
1895 err = -ENOMEM;
1896 goto failed;
1897 }
1898
Johan Hedberg2b76f452013-03-15 17:07:04 -05001899 hci_req_init(&req, hdev);
1900
Johan Hedberg9a43e252013-10-20 19:00:07 +03001901 /* If BR/EDR is not enabled and we disable advertising as a
1902 * by-product of disabling connectable, we need to update the
1903 * advertising flags.
1904 */
1905 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1906 if (!cp->val) {
1907 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1908 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1909 }
1910 update_adv_data(&req);
1911 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001912 if (cp->val) {
1913 scan = SCAN_PAGE;
1914 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001915 /* If we don't have any whitelist entries just
1916 * disable all scanning. If there are entries
1917 * and we had both page and inquiry scanning
1918 * enabled then fall back to only page scanning.
1919 * Otherwise no changes are needed.
1920 */
1921 if (list_empty(&hdev->whitelist))
1922 scan = SCAN_DISABLED;
1923 else if (test_bit(HCI_ISCAN, &hdev->flags))
1924 scan = SCAN_PAGE;
1925 else
1926 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001927
1928 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001929 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001930 cancel_delayed_work(&hdev->discov_off);
1931 }
1932
1933 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1934 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001935
Johan Hedberg3bd27242014-07-28 20:53:58 +03001936no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001937 /* If we're going from non-connectable to connectable or
1938 * vice-versa when fast connectable is enabled ensure that fast
1939 * connectable gets disabled. write_fast_connectable won't do
1940 * anything if the page scan parameters are already what they
1941 * should be.
1942 */
1943 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001944 write_fast_connectable(&req, false);
1945
Johan Hedberge8b12022014-07-10 10:51:27 +03001946 /* Update the advertising parameters if necessary */
1947 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001949
Johan Hedberg2b76f452013-03-15 17:07:04 -05001950 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001951 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001952 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001953 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001954 err = set_connectable_update_settings(hdev, sk,
1955 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001956 goto failed;
1957 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001958
1959failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001960 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001961 return err;
1962}
1963
Johan Hedbergb2939472014-07-30 09:22:23 +03001964static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001965 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001966{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001967 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001968 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001969 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001970
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001971 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001972
Johan Hedberga7e80f22013-01-09 16:05:19 +02001973 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001974 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001975 MGMT_STATUS_INVALID_PARAMS);
1976
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001977 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001978
1979 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001980 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001981 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001982 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001983
Johan Hedbergb2939472014-07-30 09:22:23 +03001984 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001985 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001986 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001987
Marcel Holtmann55594352013-10-06 16:11:57 -07001988 if (changed)
1989 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001990
Marcel Holtmann55594352013-10-06 16:11:57 -07001991unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001992 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001993 return err;
1994}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001995
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001996static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1997 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001998{
1999 struct mgmt_mode *cp = data;
2000 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002001 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002002 int err;
2003
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002004 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002005
Johan Hedberge6fe7982013-10-02 15:45:22 +03002006 status = mgmt_bredr_support(hdev);
2007 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002008 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002009 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002010
Johan Hedberga7e80f22013-01-09 16:05:19 +02002011 if (cp->val != 0x00 && cp->val != 0x01)
2012 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2013 MGMT_STATUS_INVALID_PARAMS);
2014
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002015 hci_dev_lock(hdev);
2016
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002017 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002018 bool changed = false;
2019
2020 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002021 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002022 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2023 changed = true;
2024 }
2025
2026 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2027 if (err < 0)
2028 goto failed;
2029
2030 if (changed)
2031 err = new_settings(hdev, sk);
2032
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002033 goto failed;
2034 }
2035
2036 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002037 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002038 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002039 goto failed;
2040 }
2041
2042 val = !!cp->val;
2043
2044 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2045 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2046 goto failed;
2047 }
2048
2049 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2050 if (!cmd) {
2051 err = -ENOMEM;
2052 goto failed;
2053 }
2054
2055 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2056 if (err < 0) {
2057 mgmt_pending_remove(cmd);
2058 goto failed;
2059 }
2060
2061failed:
2062 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002063 return err;
2064}
2065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002066static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002067{
2068 struct mgmt_mode *cp = data;
2069 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002070 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002071 int err;
2072
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002073 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002074
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002075 status = mgmt_bredr_support(hdev);
2076 if (status)
2077 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2078
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002079 if (!lmp_ssp_capable(hdev))
2080 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2081 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002082
Johan Hedberga7e80f22013-01-09 16:05:19 +02002083 if (cp->val != 0x00 && cp->val != 0x01)
2084 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2085 MGMT_STATUS_INVALID_PARAMS);
2086
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002087 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002088
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002089 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002090 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002091
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002092 if (cp->val) {
2093 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2094 &hdev->dev_flags);
2095 } else {
2096 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2097 &hdev->dev_flags);
2098 if (!changed)
2099 changed = test_and_clear_bit(HCI_HS_ENABLED,
2100 &hdev->dev_flags);
2101 else
2102 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002103 }
2104
2105 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2106 if (err < 0)
2107 goto failed;
2108
2109 if (changed)
2110 err = new_settings(hdev, sk);
2111
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002112 goto failed;
2113 }
2114
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002115 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2116 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002117 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2118 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002119 goto failed;
2120 }
2121
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002122 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002123 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2124 goto failed;
2125 }
2126
2127 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2128 if (!cmd) {
2129 err = -ENOMEM;
2130 goto failed;
2131 }
2132
Johan Hedberg37699722014-06-24 14:00:27 +03002133 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2134 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2135 sizeof(cp->val), &cp->val);
2136
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002137 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002138 if (err < 0) {
2139 mgmt_pending_remove(cmd);
2140 goto failed;
2141 }
2142
2143failed:
2144 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002145 return err;
2146}
2147
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002148static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002149{
2150 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002151 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002152 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002153 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002154
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002155 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002156
Johan Hedberge6fe7982013-10-02 15:45:22 +03002157 status = mgmt_bredr_support(hdev);
2158 if (status)
2159 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002160
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002161 if (!lmp_ssp_capable(hdev))
2162 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2163 MGMT_STATUS_NOT_SUPPORTED);
2164
2165 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2166 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2167 MGMT_STATUS_REJECTED);
2168
Johan Hedberga7e80f22013-01-09 16:05:19 +02002169 if (cp->val != 0x00 && cp->val != 0x01)
2170 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2171 MGMT_STATUS_INVALID_PARAMS);
2172
Marcel Holtmannee392692013-10-01 22:59:23 -07002173 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002174
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002175 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002176 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002177 } else {
2178 if (hdev_is_powered(hdev)) {
2179 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2180 MGMT_STATUS_REJECTED);
2181 goto unlock;
2182 }
2183
Marcel Holtmannee392692013-10-01 22:59:23 -07002184 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002185 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002186
2187 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2188 if (err < 0)
2189 goto unlock;
2190
2191 if (changed)
2192 err = new_settings(hdev, sk);
2193
2194unlock:
2195 hci_dev_unlock(hdev);
2196 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002197}
2198
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002199static void le_enable_complete(struct hci_dev *hdev, u8 status)
2200{
2201 struct cmd_lookup match = { NULL, hdev };
2202
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302203 hci_dev_lock(hdev);
2204
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002205 if (status) {
2206 u8 mgmt_err = mgmt_status(status);
2207
2208 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2209 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302210 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002211 }
2212
2213 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2214
2215 new_settings(hdev, match.sk);
2216
2217 if (match.sk)
2218 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002219
2220 /* Make sure the controller has a good default for
2221 * advertising data. Restrict the update to when LE
2222 * has actually been enabled. During power on, the
2223 * update in powered_update_hci will take care of it.
2224 */
2225 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2226 struct hci_request req;
2227
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002228 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002229 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002230 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002231 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002232 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002233 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302234
2235unlock:
2236 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237}
2238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002239static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240{
2241 struct mgmt_mode *cp = data;
2242 struct hci_cp_write_le_host_supported hci_cp;
2243 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002244 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002245 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002246 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002248 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002249
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002250 if (!lmp_le_capable(hdev))
2251 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2252 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002253
Johan Hedberga7e80f22013-01-09 16:05:19 +02002254 if (cp->val != 0x00 && cp->val != 0x01)
2255 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2256 MGMT_STATUS_INVALID_PARAMS);
2257
Johan Hedbergc73eee92013-04-19 18:35:21 +03002258 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002259 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002260 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2261 MGMT_STATUS_REJECTED);
2262
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002263 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002264
2265 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002266 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002267
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002268 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002269 bool changed = false;
2270
2271 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2272 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2273 changed = true;
2274 }
2275
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002276 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2277 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002278 changed = true;
2279 }
2280
Johan Hedberg06199cf2012-02-22 16:37:11 +02002281 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2282 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002283 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002284
2285 if (changed)
2286 err = new_settings(hdev, sk);
2287
Johan Hedberg1de028c2012-02-29 19:55:35 -08002288 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002289 }
2290
Johan Hedberg4375f102013-09-25 13:26:10 +03002291 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2292 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002293 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002294 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002295 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002296 }
2297
2298 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2299 if (!cmd) {
2300 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002301 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002302 }
2303
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002304 hci_req_init(&req, hdev);
2305
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306 memset(&hci_cp, 0, sizeof(hci_cp));
2307
2308 if (val) {
2309 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002310 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002311 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002312 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002313 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314 }
2315
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002316 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2317 &hci_cp);
2318
2319 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302320 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002322
Johan Hedberg1de028c2012-02-29 19:55:35 -08002323unlock:
2324 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002325 return err;
2326}
2327
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002328/* This is a helper function to test for pending mgmt commands that can
2329 * cause CoD or EIR HCI commands. We can only allow one such pending
2330 * mgmt command at a time since otherwise we cannot easily track what
2331 * the current values are, will be, and based on that calculate if a new
2332 * HCI command needs to be sent and if yes with what value.
2333 */
2334static bool pending_eir_or_class(struct hci_dev *hdev)
2335{
2336 struct pending_cmd *cmd;
2337
2338 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2339 switch (cmd->opcode) {
2340 case MGMT_OP_ADD_UUID:
2341 case MGMT_OP_REMOVE_UUID:
2342 case MGMT_OP_SET_DEV_CLASS:
2343 case MGMT_OP_SET_POWERED:
2344 return true;
2345 }
2346 }
2347
2348 return false;
2349}
2350
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002351static const u8 bluetooth_base_uuid[] = {
2352 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2353 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2354};
2355
2356static u8 get_uuid_size(const u8 *uuid)
2357{
2358 u32 val;
2359
2360 if (memcmp(uuid, bluetooth_base_uuid, 12))
2361 return 128;
2362
2363 val = get_unaligned_le32(&uuid[12]);
2364 if (val > 0xffff)
2365 return 32;
2366
2367 return 16;
2368}
2369
Johan Hedberg92da6092013-03-15 17:06:55 -05002370static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2371{
2372 struct pending_cmd *cmd;
2373
2374 hci_dev_lock(hdev);
2375
2376 cmd = mgmt_pending_find(mgmt_op, hdev);
2377 if (!cmd)
2378 goto unlock;
2379
2380 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2381 hdev->dev_class, 3);
2382
2383 mgmt_pending_remove(cmd);
2384
2385unlock:
2386 hci_dev_unlock(hdev);
2387}
2388
2389static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2390{
2391 BT_DBG("status 0x%02x", status);
2392
2393 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002397{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002398 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002399 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002400 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 int err;
2403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002405
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002406 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002407
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002408 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002409 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002410 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002411 goto failed;
2412 }
2413
Andre Guedes92c4c202012-06-07 19:05:44 -03002414 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415 if (!uuid) {
2416 err = -ENOMEM;
2417 goto failed;
2418 }
2419
2420 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002421 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002422 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002423
Johan Hedbergde66aa62013-01-27 00:31:27 +02002424 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425
Johan Hedberg890ea892013-03-15 17:06:52 -05002426 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002427
Johan Hedberg890ea892013-03-15 17:06:52 -05002428 update_class(&req);
2429 update_eir(&req);
2430
Johan Hedberg92da6092013-03-15 17:06:55 -05002431 err = hci_req_run(&req, add_uuid_complete);
2432 if (err < 0) {
2433 if (err != -ENODATA)
2434 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002435
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002436 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002437 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002438 goto failed;
2439 }
2440
2441 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002442 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002443 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002444 goto failed;
2445 }
2446
2447 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002448
2449failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002450 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002451 return err;
2452}
2453
Johan Hedberg24b78d02012-02-23 23:24:30 +02002454static bool enable_service_cache(struct hci_dev *hdev)
2455{
2456 if (!hdev_is_powered(hdev))
2457 return false;
2458
2459 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002460 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2461 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002462 return true;
2463 }
2464
2465 return false;
2466}
2467
Johan Hedberg92da6092013-03-15 17:06:55 -05002468static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2469{
2470 BT_DBG("status 0x%02x", status);
2471
2472 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2473}
2474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002475static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002476 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002477{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002478 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002479 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002480 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481 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 -05002482 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002483 int err, found;
2484
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002485 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002486
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002487 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002488
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002489 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002491 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002492 goto unlock;
2493 }
2494
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002495 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002496 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002497
Johan Hedberg24b78d02012-02-23 23:24:30 +02002498 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002499 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002500 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002501 goto unlock;
2502 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002503
Johan Hedberg9246a862012-02-23 21:33:16 +02002504 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002505 }
2506
2507 found = 0;
2508
Johan Hedberg056341c2013-01-27 00:31:30 +02002509 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002510 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2511 continue;
2512
2513 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002514 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002515 found++;
2516 }
2517
2518 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002520 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002521 goto unlock;
2522 }
2523
Johan Hedberg9246a862012-02-23 21:33:16 +02002524update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002525 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002526
Johan Hedberg890ea892013-03-15 17:06:52 -05002527 update_class(&req);
2528 update_eir(&req);
2529
Johan Hedberg92da6092013-03-15 17:06:55 -05002530 err = hci_req_run(&req, remove_uuid_complete);
2531 if (err < 0) {
2532 if (err != -ENODATA)
2533 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002534
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002535 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002536 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002537 goto unlock;
2538 }
2539
2540 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002541 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002542 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002543 goto unlock;
2544 }
2545
2546 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002547
2548unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002549 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002550 return err;
2551}
2552
Johan Hedberg92da6092013-03-15 17:06:55 -05002553static void set_class_complete(struct hci_dev *hdev, u8 status)
2554{
2555 BT_DBG("status 0x%02x", status);
2556
2557 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2558}
2559
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002560static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002561 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002562{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002563 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002564 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002565 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002566 int err;
2567
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002568 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002569
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002570 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002571 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2572 MGMT_STATUS_NOT_SUPPORTED);
2573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002574 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002575
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002576 if (pending_eir_or_class(hdev)) {
2577 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2578 MGMT_STATUS_BUSY);
2579 goto unlock;
2580 }
2581
2582 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2583 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2584 MGMT_STATUS_INVALID_PARAMS);
2585 goto unlock;
2586 }
2587
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002588 hdev->major_class = cp->major;
2589 hdev->minor_class = cp->minor;
2590
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002591 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002594 goto unlock;
2595 }
2596
Johan Hedberg890ea892013-03-15 17:06:52 -05002597 hci_req_init(&req, hdev);
2598
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002599 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002600 hci_dev_unlock(hdev);
2601 cancel_delayed_work_sync(&hdev->service_cache);
2602 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002603 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002604 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002605
Johan Hedberg890ea892013-03-15 17:06:52 -05002606 update_class(&req);
2607
Johan Hedberg92da6092013-03-15 17:06:55 -05002608 err = hci_req_run(&req, set_class_complete);
2609 if (err < 0) {
2610 if (err != -ENODATA)
2611 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002612
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002613 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002614 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002615 goto unlock;
2616 }
2617
2618 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002619 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002620 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002621 goto unlock;
2622 }
2623
2624 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002625
Johan Hedbergb5235a62012-02-21 14:32:24 +02002626unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002627 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002628 return err;
2629}
2630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002631static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002632 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002634 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002635 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2636 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002637 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002638 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002639 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002641 BT_DBG("request for %s", hdev->name);
2642
2643 if (!lmp_bredr_capable(hdev))
2644 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2645 MGMT_STATUS_NOT_SUPPORTED);
2646
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002647 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002648 if (key_count > max_key_count) {
2649 BT_ERR("load_link_keys: too big key_count value %u",
2650 key_count);
2651 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2652 MGMT_STATUS_INVALID_PARAMS);
2653 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654
Johan Hedberg86742e12011-11-07 23:13:38 +02002655 expected_len = sizeof(*cp) + key_count *
2656 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002657 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002658 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002659 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002660 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002661 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002662 }
2663
Johan Hedberg4ae14302013-01-20 14:27:13 +02002664 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2665 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2666 MGMT_STATUS_INVALID_PARAMS);
2667
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002668 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002669 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002670
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002671 for (i = 0; i < key_count; i++) {
2672 struct mgmt_link_key_info *key = &cp->keys[i];
2673
Marcel Holtmann8e991132014-01-10 02:07:25 -08002674 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002675 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2676 MGMT_STATUS_INVALID_PARAMS);
2677 }
2678
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002679 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680
2681 hci_link_keys_clear(hdev);
2682
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002683 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002684 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2685 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002686 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002687 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2688 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002689
2690 if (changed)
2691 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002692
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002693 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002694 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695
Johan Hedberg58e92932014-06-24 14:00:26 +03002696 /* Always ignore debug keys and require a new pairing if
2697 * the user wants to use them.
2698 */
2699 if (key->type == HCI_LK_DEBUG_COMBINATION)
2700 continue;
2701
Johan Hedberg7652ff62014-06-24 13:15:49 +03002702 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2703 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704 }
2705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002706 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002707
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002708 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002709
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002710 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711}
2712
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002713static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002715{
2716 struct mgmt_ev_device_unpaired ev;
2717
2718 bacpy(&ev.addr.bdaddr, bdaddr);
2719 ev.addr.type = addr_type;
2720
2721 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002722 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002723}
2724
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002725static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002728 struct mgmt_cp_unpair_device *cp = data;
2729 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002730 struct hci_cp_disconnect dc;
2731 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733 int err;
2734
Johan Hedberga8a1d192011-11-10 15:54:38 +02002735 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002736 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2737 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002738
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002739 if (!bdaddr_type_is_valid(cp->addr.type))
2740 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2741 MGMT_STATUS_INVALID_PARAMS,
2742 &rp, sizeof(rp));
2743
Johan Hedberg118da702013-01-20 14:27:20 +02002744 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2745 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2746 MGMT_STATUS_INVALID_PARAMS,
2747 &rp, sizeof(rp));
2748
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002749 hci_dev_lock(hdev);
2750
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002751 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002752 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002753 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002754 goto unlock;
2755 }
2756
Johan Hedberge0b2b272014-02-18 17:14:31 +02002757 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002758 /* If disconnection is requested, then look up the
2759 * connection. If the remote device is connected, it
2760 * will be later used to terminate the link.
2761 *
2762 * Setting it to NULL explicitly will cause no
2763 * termination of the link.
2764 */
2765 if (cp->disconnect)
2766 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2767 &cp->addr.bdaddr);
2768 else
2769 conn = NULL;
2770
Johan Hedberg124f6e32012-02-09 13:50:12 +02002771 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002772 } else {
2773 u8 addr_type;
2774
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002775 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2776 &cp->addr.bdaddr);
2777 if (conn) {
2778 /* Defer clearing up the connection parameters
2779 * until closing to give a chance of keeping
2780 * them if a repairing happens.
2781 */
2782 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2783
2784 /* If disconnection is not requested, then
2785 * clear the connection variable so that the
2786 * link is not terminated.
2787 */
2788 if (!cp->disconnect)
2789 conn = NULL;
2790 }
2791
Johan Hedberge0b2b272014-02-18 17:14:31 +02002792 if (cp->addr.type == BDADDR_LE_PUBLIC)
2793 addr_type = ADDR_LE_DEV_PUBLIC;
2794 else
2795 addr_type = ADDR_LE_DEV_RANDOM;
2796
Johan Hedberga7ec7332014-02-18 17:14:35 +02002797 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2798
Johan Hedberge0b2b272014-02-18 17:14:31 +02002799 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2800 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002801
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002802 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002803 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002804 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002805 goto unlock;
2806 }
2807
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002808 /* If the connection variable is set, then termination of the
2809 * link is requested.
2810 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002811 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002812 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002813 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002814 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002815 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002816 }
2817
Johan Hedberg124f6e32012-02-09 13:50:12 +02002818 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002819 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002820 if (!cmd) {
2821 err = -ENOMEM;
2822 goto unlock;
2823 }
2824
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002825 cmd->cmd_complete = addr_cmd_complete;
2826
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002827 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002828 dc.reason = 0x13; /* Remote User Terminated Connection */
2829 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2830 if (err < 0)
2831 mgmt_pending_remove(cmd);
2832
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002833unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002834 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835 return err;
2836}
2837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002838static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002839 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002840{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002841 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002842 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002843 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002845 int err;
2846
2847 BT_DBG("");
2848
Johan Hedberg06a63b12013-01-20 14:27:21 +02002849 memset(&rp, 0, sizeof(rp));
2850 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2851 rp.addr.type = cp->addr.type;
2852
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002853 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002854 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2855 MGMT_STATUS_INVALID_PARAMS,
2856 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002857
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002858 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002859
2860 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002861 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2862 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002863 goto failed;
2864 }
2865
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002866 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002867 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2868 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002869 goto failed;
2870 }
2871
Andre Guedes591f47f2012-04-24 21:02:49 -03002872 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002873 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2874 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002875 else
2876 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002877
Vishal Agarwalf9607272012-06-13 05:32:43 +05302878 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002879 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2880 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 goto failed;
2882 }
2883
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002884 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002885 if (!cmd) {
2886 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002887 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002888 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002889
Johan Hedbergf5818c22014-12-05 13:36:02 +02002890 cmd->cmd_complete = generic_cmd_complete;
2891
Johan Hedberge3f2f922014-08-18 20:33:33 +03002892 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002893 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002894 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895
2896failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002897 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002898 return err;
2899}
2900
Andre Guedes57c14772012-04-24 21:02:50 -03002901static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002902{
2903 switch (link_type) {
2904 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002905 switch (addr_type) {
2906 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002907 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002908
Johan Hedberg48264f02011-11-09 13:58:58 +02002909 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002910 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002911 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002912 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002913
Johan Hedberg4c659c32011-11-07 23:13:39 +02002914 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002915 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002916 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002917 }
2918}
2919
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2921 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002922{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002923 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002924 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002925 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002926 int err;
2927 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002928
2929 BT_DBG("");
2930
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002931 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002932
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002933 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002936 goto unlock;
2937 }
2938
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002939 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002940 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2941 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002942 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002943 }
2944
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002945 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002946 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002947 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002948 err = -ENOMEM;
2949 goto unlock;
2950 }
2951
Johan Hedberg2784eb42011-01-21 13:56:35 +02002952 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002954 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2955 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002957 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002958 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002959 continue;
2960 i++;
2961 }
2962
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002963 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002964
Johan Hedberg4c659c32011-11-07 23:13:39 +02002965 /* Recalculate length in case of filtered SCO connections, etc */
2966 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002968 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002969 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002970
Johan Hedberga38528f2011-01-22 06:46:43 +02002971 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002972
2973unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002974 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002975 return err;
2976}
2977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002978static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002980{
2981 struct pending_cmd *cmd;
2982 int err;
2983
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002984 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002986 if (!cmd)
2987 return -ENOMEM;
2988
Johan Hedbergd8457692012-02-17 14:24:57 +02002989 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002990 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002991 if (err < 0)
2992 mgmt_pending_remove(cmd);
2993
2994 return err;
2995}
2996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002997static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002998 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002999{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003000 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003001 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003002 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003003 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003004 int err;
3005
3006 BT_DBG("");
3007
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003008 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003009
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003010 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003011 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003013 goto failed;
3014 }
3015
Johan Hedbergd8457692012-02-17 14:24:57 +02003016 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003018 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003020 goto failed;
3021 }
3022
3023 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003024 struct mgmt_cp_pin_code_neg_reply ncp;
3025
3026 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003027
3028 BT_ERR("PIN code is not 16 bytes long");
3029
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003030 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003032 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003033 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003034
3035 goto failed;
3036 }
3037
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003038 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003039 if (!cmd) {
3040 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003041 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003042 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003043
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003044 cmd->cmd_complete = addr_cmd_complete;
3045
Johan Hedbergd8457692012-02-17 14:24:57 +02003046 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003047 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003048 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003049
3050 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3051 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003052 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053
3054failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003055 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003056 return err;
3057}
3058
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003059static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3060 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003061{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003062 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003063
3064 BT_DBG("");
3065
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003066 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3067 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3068 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3069
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003070 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003071
3072 hdev->io_capability = cp->io_capability;
3073
3074 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003075 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003076
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003077 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003078
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3080 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003081}
3082
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003083static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084{
3085 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003086 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003087
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003088 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3090 continue;
3091
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092 if (cmd->user_data != conn)
3093 continue;
3094
3095 return cmd;
3096 }
3097
3098 return NULL;
3099}
3100
3101static void pairing_complete(struct pending_cmd *cmd, u8 status)
3102{
3103 struct mgmt_rp_pair_device rp;
3104 struct hci_conn *conn = cmd->user_data;
3105
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003106 bacpy(&rp.addr.bdaddr, &conn->dst);
3107 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003108
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003109 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003110 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003111
3112 /* So we don't get further callbacks for this connection */
3113 conn->connect_cfm_cb = NULL;
3114 conn->security_cfm_cb = NULL;
3115 conn->disconn_cfm_cb = NULL;
3116
David Herrmann76a68ba2013-04-06 20:28:37 +02003117 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003118
3119 /* The device is paired so there is no need to remove
3120 * its connection parameters anymore.
3121 */
3122 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003123
3124 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003125}
3126
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003127void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3128{
3129 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3130 struct pending_cmd *cmd;
3131
3132 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003133 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003134 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003135 mgmt_pending_remove(cmd);
3136 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003137}
3138
Johan Hedberge9a416b2011-02-19 12:05:56 -03003139static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3140{
3141 struct pending_cmd *cmd;
3142
3143 BT_DBG("status %u", status);
3144
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003145 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003146 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003147 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003148 return;
3149 }
3150
3151 cmd->cmd_complete(cmd, mgmt_status(status));
3152 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003153}
3154
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003155static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303156{
3157 struct pending_cmd *cmd;
3158
3159 BT_DBG("status %u", status);
3160
3161 if (!status)
3162 return;
3163
3164 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003165 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303166 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003167 return;
3168 }
3169
3170 cmd->cmd_complete(cmd, mgmt_status(status));
3171 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303172}
3173
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003174static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003175 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003176{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003177 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003178 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003179 struct pending_cmd *cmd;
3180 u8 sec_level, auth_type;
3181 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003182 int err;
3183
3184 BT_DBG("");
3185
Szymon Jancf950a30e2013-01-18 12:48:07 +01003186 memset(&rp, 0, sizeof(rp));
3187 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3188 rp.addr.type = cp->addr.type;
3189
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003190 if (!bdaddr_type_is_valid(cp->addr.type))
3191 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3192 MGMT_STATUS_INVALID_PARAMS,
3193 &rp, sizeof(rp));
3194
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003195 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3196 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3197 MGMT_STATUS_INVALID_PARAMS,
3198 &rp, sizeof(rp));
3199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003200 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003201
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003202 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003203 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3204 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003205 goto unlock;
3206 }
3207
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003208 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003209 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003210
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003211 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003212 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3213 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003214 } else {
3215 u8 addr_type;
3216
3217 /* Convert from L2CAP channel address type to HCI address type
3218 */
3219 if (cp->addr.type == BDADDR_LE_PUBLIC)
3220 addr_type = ADDR_LE_DEV_PUBLIC;
3221 else
3222 addr_type = ADDR_LE_DEV_RANDOM;
3223
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003224 /* When pairing a new device, it is expected to remember
3225 * this device for future connections. Adding the connection
3226 * parameter information ahead of time allows tracking
3227 * of the slave preferred values and will speed up any
3228 * further connection establishment.
3229 *
3230 * If connection parameters already exist, then they
3231 * will be kept and this function does nothing.
3232 */
3233 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3234
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003235 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003236 sec_level, HCI_LE_CONN_TIMEOUT,
3237 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003238 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003239
Ville Tervo30e76272011-02-22 16:10:53 -03003240 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003241 int status;
3242
3243 if (PTR_ERR(conn) == -EBUSY)
3244 status = MGMT_STATUS_BUSY;
3245 else
3246 status = MGMT_STATUS_CONNECT_FAILED;
3247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003248 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003249 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003250 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003251 goto unlock;
3252 }
3253
3254 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003255 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003256 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003257 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003258 goto unlock;
3259 }
3260
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003261 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003262 if (!cmd) {
3263 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003264 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003265 goto unlock;
3266 }
3267
Johan Hedberg04ab2742014-12-05 13:36:04 +02003268 cmd->cmd_complete = pairing_complete;
3269
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003270 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003271 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003272 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003273 conn->security_cfm_cb = pairing_complete_cb;
3274 conn->disconn_cfm_cb = pairing_complete_cb;
3275 } else {
3276 conn->connect_cfm_cb = le_pairing_complete_cb;
3277 conn->security_cfm_cb = le_pairing_complete_cb;
3278 conn->disconn_cfm_cb = le_pairing_complete_cb;
3279 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003280
Johan Hedberge9a416b2011-02-19 12:05:56 -03003281 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003282 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003283
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003284 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003285 hci_conn_security(conn, sec_level, auth_type, true)) {
3286 cmd->cmd_complete(cmd, 0);
3287 mgmt_pending_remove(cmd);
3288 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003289
3290 err = 0;
3291
3292unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003293 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003294 return err;
3295}
3296
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003297static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3298 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003299{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003300 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003301 struct pending_cmd *cmd;
3302 struct hci_conn *conn;
3303 int err;
3304
3305 BT_DBG("");
3306
Johan Hedberg28424702012-02-02 04:02:29 +02003307 hci_dev_lock(hdev);
3308
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003309 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003312 goto unlock;
3313 }
3314
Johan Hedberg28424702012-02-02 04:02:29 +02003315 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3316 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003317 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003318 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003319 goto unlock;
3320 }
3321
3322 conn = cmd->user_data;
3323
3324 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003325 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003326 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003327 goto unlock;
3328 }
3329
Johan Hedberga511b352014-12-11 21:45:45 +02003330 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3331 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003332
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003333 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003334 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003335unlock:
3336 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003337 return err;
3338}
3339
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003340static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003341 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003342 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003343{
Johan Hedberga5c29682011-02-19 12:05:57 -03003344 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003345 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003346 int err;
3347
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003348 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003349
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003350 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003351 err = cmd_complete(sk, hdev->id, mgmt_op,
3352 MGMT_STATUS_NOT_POWERED, addr,
3353 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003354 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003355 }
3356
Johan Hedberg1707c602013-03-15 17:07:15 -05003357 if (addr->type == BDADDR_BREDR)
3358 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003359 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003360 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003361
Johan Hedberg272d90d2012-02-09 15:26:12 +02003362 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003363 err = cmd_complete(sk, hdev->id, mgmt_op,
3364 MGMT_STATUS_NOT_CONNECTED, addr,
3365 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003366 goto done;
3367 }
3368
Johan Hedberg1707c602013-03-15 17:07:15 -05003369 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003370 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003371 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003372 err = cmd_complete(sk, hdev->id, mgmt_op,
3373 MGMT_STATUS_SUCCESS, addr,
3374 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003375 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003376 err = cmd_complete(sk, hdev->id, mgmt_op,
3377 MGMT_STATUS_FAILED, addr,
3378 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003379
Brian Gix47c15e22011-11-16 13:53:14 -08003380 goto done;
3381 }
3382
Johan Hedberg1707c602013-03-15 17:07:15 -05003383 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003384 if (!cmd) {
3385 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003386 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003387 }
3388
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003389 cmd->cmd_complete = addr_cmd_complete;
3390
Brian Gix0df4c182011-11-16 13:53:13 -08003391 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003392 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3393 struct hci_cp_user_passkey_reply cp;
3394
Johan Hedberg1707c602013-03-15 17:07:15 -05003395 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003396 cp.passkey = passkey;
3397 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3398 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003399 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3400 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003401
Johan Hedberga664b5b2011-02-19 12:06:02 -03003402 if (err < 0)
3403 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003404
Brian Gix0df4c182011-11-16 13:53:13 -08003405done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003406 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003407 return err;
3408}
3409
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303410static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3411 void *data, u16 len)
3412{
3413 struct mgmt_cp_pin_code_neg_reply *cp = data;
3414
3415 BT_DBG("");
3416
Johan Hedberg1707c602013-03-15 17:07:15 -05003417 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303418 MGMT_OP_PIN_CODE_NEG_REPLY,
3419 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3420}
3421
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003422static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3423 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003424{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003425 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003426
3427 BT_DBG("");
3428
3429 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003430 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003431 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003432
Johan Hedberg1707c602013-03-15 17:07:15 -05003433 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003434 MGMT_OP_USER_CONFIRM_REPLY,
3435 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003436}
3437
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003438static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003440{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003441 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003442
3443 BT_DBG("");
3444
Johan Hedberg1707c602013-03-15 17:07:15 -05003445 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003446 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3447 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003448}
3449
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003450static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3451 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003452{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003453 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003454
3455 BT_DBG("");
3456
Johan Hedberg1707c602013-03-15 17:07:15 -05003457 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003458 MGMT_OP_USER_PASSKEY_REPLY,
3459 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003460}
3461
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003462static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003463 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003464{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003465 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003466
3467 BT_DBG("");
3468
Johan Hedberg1707c602013-03-15 17:07:15 -05003469 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003470 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3471 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003472}
3473
Johan Hedberg13928972013-03-15 17:07:00 -05003474static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003475{
Johan Hedberg13928972013-03-15 17:07:00 -05003476 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003477 struct hci_cp_write_local_name cp;
3478
Johan Hedberg13928972013-03-15 17:07:00 -05003479 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003480
Johan Hedberg890ea892013-03-15 17:06:52 -05003481 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003482}
3483
Johan Hedberg13928972013-03-15 17:07:00 -05003484static void set_name_complete(struct hci_dev *hdev, u8 status)
3485{
3486 struct mgmt_cp_set_local_name *cp;
3487 struct pending_cmd *cmd;
3488
3489 BT_DBG("status 0x%02x", status);
3490
3491 hci_dev_lock(hdev);
3492
3493 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3494 if (!cmd)
3495 goto unlock;
3496
3497 cp = cmd->param;
3498
3499 if (status)
3500 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3501 mgmt_status(status));
3502 else
3503 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3504 cp, sizeof(*cp));
3505
3506 mgmt_pending_remove(cmd);
3507
3508unlock:
3509 hci_dev_unlock(hdev);
3510}
3511
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003512static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003513 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003514{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003515 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003516 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003517 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003518 int err;
3519
3520 BT_DBG("");
3521
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003522 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003523
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003524 /* If the old values are the same as the new ones just return a
3525 * direct command complete event.
3526 */
3527 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3528 !memcmp(hdev->short_name, cp->short_name,
3529 sizeof(hdev->short_name))) {
3530 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3531 data, len);
3532 goto failed;
3533 }
3534
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003535 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003536
Johan Hedbergb5235a62012-02-21 14:32:24 +02003537 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003538 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003539
3540 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003541 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003542 if (err < 0)
3543 goto failed;
3544
3545 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003546 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003547
Johan Hedbergb5235a62012-02-21 14:32:24 +02003548 goto failed;
3549 }
3550
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003551 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003552 if (!cmd) {
3553 err = -ENOMEM;
3554 goto failed;
3555 }
3556
Johan Hedberg13928972013-03-15 17:07:00 -05003557 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3558
Johan Hedberg890ea892013-03-15 17:06:52 -05003559 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003560
3561 if (lmp_bredr_capable(hdev)) {
3562 update_name(&req);
3563 update_eir(&req);
3564 }
3565
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003566 /* The name is stored in the scan response data and so
3567 * no need to udpate the advertising data here.
3568 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003569 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003570 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003571
Johan Hedberg13928972013-03-15 17:07:00 -05003572 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003573 if (err < 0)
3574 mgmt_pending_remove(cmd);
3575
3576failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003577 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003578 return err;
3579}
3580
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003581static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003582 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003583{
Szymon Jancc35938b2011-03-22 13:12:21 +01003584 struct pending_cmd *cmd;
3585 int err;
3586
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003587 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003588
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003589 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003590
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003591 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003592 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003593 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003594 goto unlock;
3595 }
3596
Andre Guedes9a1a1992012-07-24 15:03:48 -03003597 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003598 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003599 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003600 goto unlock;
3601 }
3602
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003603 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003605 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003606 goto unlock;
3607 }
3608
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003609 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003610 if (!cmd) {
3611 err = -ENOMEM;
3612 goto unlock;
3613 }
3614
Johan Hedberg710f11c2014-05-26 11:21:22 +03003615 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003616 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3617 0, NULL);
3618 else
3619 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3620
Szymon Jancc35938b2011-03-22 13:12:21 +01003621 if (err < 0)
3622 mgmt_pending_remove(cmd);
3623
3624unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003625 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003626 return err;
3627}
3628
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003629static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003630 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003631{
Szymon Janc2763eda2011-03-22 13:12:22 +01003632 int err;
3633
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003634 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003635
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003636 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003637
Marcel Holtmannec109112014-01-10 02:07:30 -08003638 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3639 struct mgmt_cp_add_remote_oob_data *cp = data;
3640 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003641
Johan Hedbergc19a4952014-11-17 20:52:19 +02003642 if (cp->addr.type != BDADDR_BREDR) {
3643 err = cmd_complete(sk, hdev->id,
3644 MGMT_OP_ADD_REMOTE_OOB_DATA,
3645 MGMT_STATUS_INVALID_PARAMS,
3646 &cp->addr, sizeof(cp->addr));
3647 goto unlock;
3648 }
3649
Marcel Holtmannec109112014-01-10 02:07:30 -08003650 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003651 cp->addr.type, cp->hash,
3652 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003653 if (err < 0)
3654 status = MGMT_STATUS_FAILED;
3655 else
3656 status = MGMT_STATUS_SUCCESS;
3657
3658 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3659 status, &cp->addr, sizeof(cp->addr));
3660 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3661 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003662 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003663 u8 status;
3664
Johan Hedbergc19a4952014-11-17 20:52:19 +02003665 if (cp->addr.type != BDADDR_BREDR) {
3666 err = cmd_complete(sk, hdev->id,
3667 MGMT_OP_ADD_REMOTE_OOB_DATA,
3668 MGMT_STATUS_INVALID_PARAMS,
3669 &cp->addr, sizeof(cp->addr));
3670 goto unlock;
3671 }
3672
Johan Hedberg86df9202014-10-26 20:52:27 +01003673 if (bdaddr_type_is_le(cp->addr.type)) {
3674 rand192 = NULL;
3675 hash192 = NULL;
3676 } else {
3677 rand192 = cp->rand192;
3678 hash192 = cp->hash192;
3679 }
3680
Johan Hedberg81328d52014-10-26 20:33:47 +01003681 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003682 cp->addr.type, hash192, rand192,
3683 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003684 if (err < 0)
3685 status = MGMT_STATUS_FAILED;
3686 else
3687 status = MGMT_STATUS_SUCCESS;
3688
3689 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3690 status, &cp->addr, sizeof(cp->addr));
3691 } else {
3692 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3693 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3694 MGMT_STATUS_INVALID_PARAMS);
3695 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003696
Johan Hedbergc19a4952014-11-17 20:52:19 +02003697unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003698 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003699 return err;
3700}
3701
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003702static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003703 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003704{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003705 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003706 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003707 int err;
3708
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003709 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003710
Johan Hedbergc19a4952014-11-17 20:52:19 +02003711 if (cp->addr.type != BDADDR_BREDR)
3712 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3713 MGMT_STATUS_INVALID_PARAMS,
3714 &cp->addr, sizeof(cp->addr));
3715
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003716 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003717
Johan Hedbergeedbd582014-11-15 09:34:23 +02003718 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3719 hci_remote_oob_data_clear(hdev);
3720 status = MGMT_STATUS_SUCCESS;
3721 goto done;
3722 }
3723
Johan Hedberg6928a922014-10-26 20:46:09 +01003724 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003725 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003726 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003727 else
Szymon Janca6785be2012-12-13 15:11:21 +01003728 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003729
Johan Hedbergeedbd582014-11-15 09:34:23 +02003730done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003731 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003732 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003733
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003734 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003735 return err;
3736}
3737
Marcel Holtmann80190442014-12-04 11:36:36 +01003738static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003739{
Marcel Holtmann80190442014-12-04 11:36:36 +01003740 struct hci_dev *hdev = req->hdev;
3741 struct hci_cp_le_set_scan_param param_cp;
3742 struct hci_cp_le_set_scan_enable enable_cp;
3743 struct hci_cp_inquiry inq_cp;
3744 /* General inquiry access code (GIAC) */
3745 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3746 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003747 int err;
3748
Marcel Holtmann80190442014-12-04 11:36:36 +01003749 switch (hdev->discovery.type) {
3750 case DISCOV_TYPE_BREDR:
3751 *status = mgmt_bredr_support(hdev);
3752 if (*status)
3753 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003754
Marcel Holtmann80190442014-12-04 11:36:36 +01003755 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3756 *status = MGMT_STATUS_BUSY;
3757 return false;
3758 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003759
Marcel Holtmann80190442014-12-04 11:36:36 +01003760 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003761
Marcel Holtmann80190442014-12-04 11:36:36 +01003762 memset(&inq_cp, 0, sizeof(inq_cp));
3763 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3764 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3765 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3766 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003767
Marcel Holtmann80190442014-12-04 11:36:36 +01003768 case DISCOV_TYPE_LE:
3769 case DISCOV_TYPE_INTERLEAVED:
3770 *status = mgmt_le_support(hdev);
3771 if (*status)
3772 return false;
3773
3774 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3775 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3776 *status = MGMT_STATUS_NOT_SUPPORTED;
3777 return false;
3778 }
3779
3780 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3781 /* Don't let discovery abort an outgoing
3782 * connection attempt that's using directed
3783 * advertising.
3784 */
3785 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3786 BT_CONNECT)) {
3787 *status = MGMT_STATUS_REJECTED;
3788 return false;
3789 }
3790
3791 disable_advertising(req);
3792 }
3793
3794 /* If controller is scanning, it means the background scanning
3795 * is running. Thus, we should temporarily stop it in order to
3796 * set the discovery scanning parameters.
3797 */
3798 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3799 hci_req_add_le_scan_disable(req);
3800
3801 memset(&param_cp, 0, sizeof(param_cp));
3802
3803 /* All active scans will be done with either a resolvable
3804 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003805 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003806 */
3807 err = hci_update_random_address(req, true, &own_addr_type);
3808 if (err < 0) {
3809 *status = MGMT_STATUS_FAILED;
3810 return false;
3811 }
3812
3813 param_cp.type = LE_SCAN_ACTIVE;
3814 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3815 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3816 param_cp.own_address_type = own_addr_type;
3817 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3818 &param_cp);
3819
3820 memset(&enable_cp, 0, sizeof(enable_cp));
3821 enable_cp.enable = LE_SCAN_ENABLE;
3822 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3823 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3824 &enable_cp);
3825 break;
3826
3827 default:
3828 *status = MGMT_STATUS_INVALID_PARAMS;
3829 return false;
3830 }
3831
3832 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003833}
3834
Andre Guedes7c307722013-04-30 15:29:28 -03003835static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3836{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003837 struct pending_cmd *cmd;
3838 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003839
Andre Guedes7c307722013-04-30 15:29:28 -03003840 BT_DBG("status %d", status);
3841
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003842 hci_dev_lock(hdev);
3843
3844 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003845 if (!cmd)
3846 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3847
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003848 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003849 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003850 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003851 }
3852
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003853 if (status) {
3854 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3855 goto unlock;
3856 }
3857
Andre Guedes7c307722013-04-30 15:29:28 -03003858 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003859
3860 switch (hdev->discovery.type) {
3861 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003862 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003863 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003864 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003865 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003866 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003867 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003868 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003869 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003870 default:
3871 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003872 timeout = 0;
3873 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003874 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003875
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003876 if (timeout)
3877 queue_delayed_work(hdev->workqueue,
3878 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003879
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003880unlock:
3881 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003882}
3883
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003884static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003885 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003886{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003887 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003888 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003889 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003890 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003891 int err;
3892
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003893 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003894
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003895 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003896
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003897 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003898 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3899 MGMT_STATUS_NOT_POWERED,
3900 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003901 goto failed;
3902 }
3903
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003904 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3905 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003906 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3907 MGMT_STATUS_BUSY, &cp->type,
3908 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003909 goto failed;
3910 }
3911
Johan Hedberg2922a942014-12-05 13:36:06 +02003912 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003913 if (!cmd) {
3914 err = -ENOMEM;
3915 goto failed;
3916 }
3917
Johan Hedberg2922a942014-12-05 13:36:06 +02003918 cmd->cmd_complete = generic_cmd_complete;
3919
Marcel Holtmann22078802014-12-05 11:45:22 +01003920 /* Clear the discovery filter first to free any previously
3921 * allocated memory for the UUID list.
3922 */
3923 hci_discovery_filter_clear(hdev);
3924
Andre Guedes4aab14e2012-02-17 20:39:36 -03003925 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003926 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003927
Andre Guedes7c307722013-04-30 15:29:28 -03003928 hci_req_init(&req, hdev);
3929
Marcel Holtmann80190442014-12-04 11:36:36 +01003930 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003931 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003932 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003933 mgmt_pending_remove(cmd);
3934 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003935 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003936
Andre Guedes7c307722013-04-30 15:29:28 -03003937 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003938 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003939 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003940 goto failed;
3941 }
3942
3943 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003944
3945failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003946 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003947 return err;
3948}
3949
Johan Hedberg2922a942014-12-05 13:36:06 +02003950static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03003951{
Johan Hedberg2922a942014-12-05 13:36:06 +02003952 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
3953}
3954
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003955static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3956 void *data, u16 len)
3957{
3958 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003959 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003960 struct hci_request req;
3961 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3962 u16 uuid_count, expected_len;
3963 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003964 int err;
3965
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003966 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003967
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003968 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003969
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003970 if (!hdev_is_powered(hdev)) {
3971 err = cmd_complete(sk, hdev->id,
3972 MGMT_OP_START_SERVICE_DISCOVERY,
3973 MGMT_STATUS_NOT_POWERED,
3974 &cp->type, sizeof(cp->type));
3975 goto failed;
3976 }
3977
3978 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3979 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3980 err = cmd_complete(sk, hdev->id,
3981 MGMT_OP_START_SERVICE_DISCOVERY,
3982 MGMT_STATUS_BUSY, &cp->type,
3983 sizeof(cp->type));
3984 goto failed;
3985 }
3986
3987 uuid_count = __le16_to_cpu(cp->uuid_count);
3988 if (uuid_count > max_uuid_count) {
3989 BT_ERR("service_discovery: too big uuid_count value %u",
3990 uuid_count);
3991 err = cmd_complete(sk, hdev->id,
3992 MGMT_OP_START_SERVICE_DISCOVERY,
3993 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3994 sizeof(cp->type));
3995 goto failed;
3996 }
3997
3998 expected_len = sizeof(*cp) + uuid_count * 16;
3999 if (expected_len != len) {
4000 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4001 expected_len, len);
4002 err = cmd_complete(sk, hdev->id,
4003 MGMT_OP_START_SERVICE_DISCOVERY,
4004 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4005 sizeof(cp->type));
4006 goto failed;
4007 }
4008
4009 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004010 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004011 if (!cmd) {
4012 err = -ENOMEM;
4013 goto failed;
4014 }
4015
Johan Hedberg2922a942014-12-05 13:36:06 +02004016 cmd->cmd_complete = service_discovery_cmd_complete;
4017
Marcel Holtmann22078802014-12-05 11:45:22 +01004018 /* Clear the discovery filter first to free any previously
4019 * allocated memory for the UUID list.
4020 */
4021 hci_discovery_filter_clear(hdev);
4022
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004023 hdev->discovery.type = cp->type;
4024 hdev->discovery.rssi = cp->rssi;
4025 hdev->discovery.uuid_count = uuid_count;
4026
4027 if (uuid_count > 0) {
4028 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4029 GFP_KERNEL);
4030 if (!hdev->discovery.uuids) {
4031 err = cmd_complete(sk, hdev->id,
4032 MGMT_OP_START_SERVICE_DISCOVERY,
4033 MGMT_STATUS_FAILED,
4034 &cp->type, sizeof(cp->type));
4035 mgmt_pending_remove(cmd);
4036 goto failed;
4037 }
4038 }
4039
4040 hci_req_init(&req, hdev);
4041
4042 if (!trigger_discovery(&req, &status)) {
4043 err = cmd_complete(sk, hdev->id,
4044 MGMT_OP_START_SERVICE_DISCOVERY,
4045 status, &cp->type, sizeof(cp->type));
4046 mgmt_pending_remove(cmd);
4047 goto failed;
4048 }
4049
4050 err = hci_req_run(&req, start_discovery_complete);
4051 if (err < 0) {
4052 mgmt_pending_remove(cmd);
4053 goto failed;
4054 }
4055
4056 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4057
4058failed:
4059 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004060 return err;
4061}
4062
Andre Guedes0e05bba2013-04-30 15:29:33 -03004063static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4064{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004065 struct pending_cmd *cmd;
4066
Andre Guedes0e05bba2013-04-30 15:29:33 -03004067 BT_DBG("status %d", status);
4068
4069 hci_dev_lock(hdev);
4070
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004071 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4072 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004073 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004074 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004075 }
4076
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004077 if (!status)
4078 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004079
Andre Guedes0e05bba2013-04-30 15:29:33 -03004080 hci_dev_unlock(hdev);
4081}
4082
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004083static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004084 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004085{
Johan Hedbergd9306502012-02-20 23:25:18 +02004086 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004087 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004088 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004089 int err;
4090
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004091 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004092
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004093 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004094
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004095 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004096 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004097 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4098 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004099 goto unlock;
4100 }
4101
4102 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004103 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004104 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4105 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004106 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004107 }
4108
Johan Hedberg2922a942014-12-05 13:36:06 +02004109 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004110 if (!cmd) {
4111 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004112 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004113 }
4114
Johan Hedberg2922a942014-12-05 13:36:06 +02004115 cmd->cmd_complete = generic_cmd_complete;
4116
Andre Guedes0e05bba2013-04-30 15:29:33 -03004117 hci_req_init(&req, hdev);
4118
Johan Hedberg21a60d32014-06-10 14:05:58 +03004119 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004120
Johan Hedberg21a60d32014-06-10 14:05:58 +03004121 err = hci_req_run(&req, stop_discovery_complete);
4122 if (!err) {
4123 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004124 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004125 }
4126
Johan Hedberg21a60d32014-06-10 14:05:58 +03004127 mgmt_pending_remove(cmd);
4128
4129 /* If no HCI commands were sent we're done */
4130 if (err == -ENODATA) {
4131 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4132 &mgmt_cp->type, sizeof(mgmt_cp->type));
4133 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4134 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004135
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004136unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004137 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004138 return err;
4139}
4140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004141static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004142 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004143{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004144 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004145 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004146 int err;
4147
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004148 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004149
Johan Hedberg561aafb2012-01-04 13:31:59 +02004150 hci_dev_lock(hdev);
4151
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004152 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004153 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4154 MGMT_STATUS_FAILED, &cp->addr,
4155 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004156 goto failed;
4157 }
4158
Johan Hedberga198e7b2012-02-17 14:27:06 +02004159 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004160 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004161 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4162 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4163 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004164 goto failed;
4165 }
4166
4167 if (cp->name_known) {
4168 e->name_state = NAME_KNOWN;
4169 list_del(&e->list);
4170 } else {
4171 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004172 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004173 }
4174
Johan Hedberge3846622013-01-09 15:29:33 +02004175 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4176 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004177
4178failed:
4179 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004180 return err;
4181}
4182
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004183static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004184 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004185{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004186 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004187 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004188 int err;
4189
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004190 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004191
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004192 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004193 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4194 MGMT_STATUS_INVALID_PARAMS,
4195 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004196
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004197 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004198
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004199 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4200 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004201 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004202 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004203 goto done;
4204 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004205
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004206 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4207 sk);
4208 status = MGMT_STATUS_SUCCESS;
4209
4210done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004211 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004212 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004213
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004214 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004215
4216 return err;
4217}
4218
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004219static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004220 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004221{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004222 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004223 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004224 int err;
4225
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004226 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004227
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004228 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004229 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4230 MGMT_STATUS_INVALID_PARAMS,
4231 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004232
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004233 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004234
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004235 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4236 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004237 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004238 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004239 goto done;
4240 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004241
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004242 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4243 sk);
4244 status = MGMT_STATUS_SUCCESS;
4245
4246done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004247 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004248 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004249
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004250 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004251
4252 return err;
4253}
4254
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004255static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4256 u16 len)
4257{
4258 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004259 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004260 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004261 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004262
4263 BT_DBG("%s", hdev->name);
4264
Szymon Jancc72d4b82012-03-16 16:02:57 +01004265 source = __le16_to_cpu(cp->source);
4266
4267 if (source > 0x0002)
4268 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4269 MGMT_STATUS_INVALID_PARAMS);
4270
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004271 hci_dev_lock(hdev);
4272
Szymon Jancc72d4b82012-03-16 16:02:57 +01004273 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004274 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4275 hdev->devid_product = __le16_to_cpu(cp->product);
4276 hdev->devid_version = __le16_to_cpu(cp->version);
4277
4278 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4279
Johan Hedberg890ea892013-03-15 17:06:52 -05004280 hci_req_init(&req, hdev);
4281 update_eir(&req);
4282 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004283
4284 hci_dev_unlock(hdev);
4285
4286 return err;
4287}
4288
Johan Hedberg4375f102013-09-25 13:26:10 +03004289static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4290{
4291 struct cmd_lookup match = { NULL, hdev };
4292
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304293 hci_dev_lock(hdev);
4294
Johan Hedberg4375f102013-09-25 13:26:10 +03004295 if (status) {
4296 u8 mgmt_err = mgmt_status(status);
4297
4298 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4299 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304300 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004301 }
4302
Johan Hedbergc93bd152014-07-08 15:07:48 +03004303 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4304 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4305 else
4306 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4307
Johan Hedberg4375f102013-09-25 13:26:10 +03004308 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4309 &match);
4310
4311 new_settings(hdev, match.sk);
4312
4313 if (match.sk)
4314 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304315
4316unlock:
4317 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004318}
4319
Marcel Holtmann21b51872013-10-10 09:47:53 -07004320static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4321 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004322{
4323 struct mgmt_mode *cp = data;
4324 struct pending_cmd *cmd;
4325 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004326 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004327 int err;
4328
4329 BT_DBG("request for %s", hdev->name);
4330
Johan Hedberge6fe7982013-10-02 15:45:22 +03004331 status = mgmt_le_support(hdev);
4332 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004333 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004334 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004335
4336 if (cp->val != 0x00 && cp->val != 0x01)
4337 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4338 MGMT_STATUS_INVALID_PARAMS);
4339
4340 hci_dev_lock(hdev);
4341
4342 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004343 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004344
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004345 /* The following conditions are ones which mean that we should
4346 * not do any HCI communication but directly send a mgmt
4347 * response to user space (after toggling the flag if
4348 * necessary).
4349 */
4350 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004351 hci_conn_num(hdev, LE_LINK) > 0 ||
4352 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4353 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004354 bool changed = false;
4355
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004356 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4357 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004358 changed = true;
4359 }
4360
4361 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4362 if (err < 0)
4363 goto unlock;
4364
4365 if (changed)
4366 err = new_settings(hdev, sk);
4367
4368 goto unlock;
4369 }
4370
4371 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4372 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4373 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4374 MGMT_STATUS_BUSY);
4375 goto unlock;
4376 }
4377
4378 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4379 if (!cmd) {
4380 err = -ENOMEM;
4381 goto unlock;
4382 }
4383
4384 hci_req_init(&req, hdev);
4385
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004386 if (val)
4387 enable_advertising(&req);
4388 else
4389 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004390
4391 err = hci_req_run(&req, set_advertising_complete);
4392 if (err < 0)
4393 mgmt_pending_remove(cmd);
4394
4395unlock:
4396 hci_dev_unlock(hdev);
4397 return err;
4398}
4399
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004400static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4401 void *data, u16 len)
4402{
4403 struct mgmt_cp_set_static_address *cp = data;
4404 int err;
4405
4406 BT_DBG("%s", hdev->name);
4407
Marcel Holtmann62af4442013-10-02 22:10:32 -07004408 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004409 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004410 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004411
4412 if (hdev_is_powered(hdev))
4413 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4414 MGMT_STATUS_REJECTED);
4415
4416 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4417 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4418 return cmd_status(sk, hdev->id,
4419 MGMT_OP_SET_STATIC_ADDRESS,
4420 MGMT_STATUS_INVALID_PARAMS);
4421
4422 /* Two most significant bits shall be set */
4423 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4424 return cmd_status(sk, hdev->id,
4425 MGMT_OP_SET_STATIC_ADDRESS,
4426 MGMT_STATUS_INVALID_PARAMS);
4427 }
4428
4429 hci_dev_lock(hdev);
4430
4431 bacpy(&hdev->static_addr, &cp->bdaddr);
4432
4433 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4434
4435 hci_dev_unlock(hdev);
4436
4437 return err;
4438}
4439
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004440static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4441 void *data, u16 len)
4442{
4443 struct mgmt_cp_set_scan_params *cp = data;
4444 __u16 interval, window;
4445 int err;
4446
4447 BT_DBG("%s", hdev->name);
4448
4449 if (!lmp_le_capable(hdev))
4450 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4451 MGMT_STATUS_NOT_SUPPORTED);
4452
4453 interval = __le16_to_cpu(cp->interval);
4454
4455 if (interval < 0x0004 || interval > 0x4000)
4456 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4457 MGMT_STATUS_INVALID_PARAMS);
4458
4459 window = __le16_to_cpu(cp->window);
4460
4461 if (window < 0x0004 || window > 0x4000)
4462 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4463 MGMT_STATUS_INVALID_PARAMS);
4464
Marcel Holtmann899e1072013-10-14 09:55:32 -07004465 if (window > interval)
4466 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4467 MGMT_STATUS_INVALID_PARAMS);
4468
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004469 hci_dev_lock(hdev);
4470
4471 hdev->le_scan_interval = interval;
4472 hdev->le_scan_window = window;
4473
4474 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4475
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004476 /* If background scan is running, restart it so new parameters are
4477 * loaded.
4478 */
4479 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4480 hdev->discovery.state == DISCOVERY_STOPPED) {
4481 struct hci_request req;
4482
4483 hci_req_init(&req, hdev);
4484
4485 hci_req_add_le_scan_disable(&req);
4486 hci_req_add_le_passive_scan(&req);
4487
4488 hci_req_run(&req, NULL);
4489 }
4490
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004491 hci_dev_unlock(hdev);
4492
4493 return err;
4494}
4495
Johan Hedberg33e38b32013-03-15 17:07:05 -05004496static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4497{
4498 struct pending_cmd *cmd;
4499
4500 BT_DBG("status 0x%02x", status);
4501
4502 hci_dev_lock(hdev);
4503
4504 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4505 if (!cmd)
4506 goto unlock;
4507
4508 if (status) {
4509 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4510 mgmt_status(status));
4511 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004512 struct mgmt_mode *cp = cmd->param;
4513
4514 if (cp->val)
4515 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4516 else
4517 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4518
Johan Hedberg33e38b32013-03-15 17:07:05 -05004519 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4520 new_settings(hdev, cmd->sk);
4521 }
4522
4523 mgmt_pending_remove(cmd);
4524
4525unlock:
4526 hci_dev_unlock(hdev);
4527}
4528
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004529static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004530 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004531{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004532 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004533 struct pending_cmd *cmd;
4534 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004535 int err;
4536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004537 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004538
Johan Hedberg56f87902013-10-02 13:43:13 +03004539 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4540 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004541 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4542 MGMT_STATUS_NOT_SUPPORTED);
4543
Johan Hedberga7e80f22013-01-09 16:05:19 +02004544 if (cp->val != 0x00 && cp->val != 0x01)
4545 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4546 MGMT_STATUS_INVALID_PARAMS);
4547
Johan Hedberg5400c042012-02-21 16:40:33 +02004548 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004549 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004550 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004551
4552 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004553 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004554 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004555
4556 hci_dev_lock(hdev);
4557
Johan Hedberg05cbf292013-03-15 17:07:07 -05004558 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4559 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4560 MGMT_STATUS_BUSY);
4561 goto unlock;
4562 }
4563
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004564 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4565 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4566 hdev);
4567 goto unlock;
4568 }
4569
Johan Hedberg33e38b32013-03-15 17:07:05 -05004570 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4571 data, len);
4572 if (!cmd) {
4573 err = -ENOMEM;
4574 goto unlock;
4575 }
4576
4577 hci_req_init(&req, hdev);
4578
Johan Hedberg406d7802013-03-15 17:07:09 -05004579 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004580
4581 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004582 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004583 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004584 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004585 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004586 }
4587
Johan Hedberg33e38b32013-03-15 17:07:05 -05004588unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004589 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004590
Antti Julkuf6422ec2011-06-22 13:11:56 +03004591 return err;
4592}
4593
Johan Hedberg0663ca22013-10-02 13:43:14 +03004594static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4595{
4596 struct pending_cmd *cmd;
4597
4598 BT_DBG("status 0x%02x", status);
4599
4600 hci_dev_lock(hdev);
4601
4602 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4603 if (!cmd)
4604 goto unlock;
4605
4606 if (status) {
4607 u8 mgmt_err = mgmt_status(status);
4608
4609 /* We need to restore the flag if related HCI commands
4610 * failed.
4611 */
4612 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4613
4614 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4615 } else {
4616 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4617 new_settings(hdev, cmd->sk);
4618 }
4619
4620 mgmt_pending_remove(cmd);
4621
4622unlock:
4623 hci_dev_unlock(hdev);
4624}
4625
4626static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4627{
4628 struct mgmt_mode *cp = data;
4629 struct pending_cmd *cmd;
4630 struct hci_request req;
4631 int err;
4632
4633 BT_DBG("request for %s", hdev->name);
4634
4635 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4636 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4637 MGMT_STATUS_NOT_SUPPORTED);
4638
4639 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4640 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4641 MGMT_STATUS_REJECTED);
4642
4643 if (cp->val != 0x00 && cp->val != 0x01)
4644 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4645 MGMT_STATUS_INVALID_PARAMS);
4646
4647 hci_dev_lock(hdev);
4648
4649 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4650 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4651 goto unlock;
4652 }
4653
4654 if (!hdev_is_powered(hdev)) {
4655 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004656 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4657 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4658 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4659 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4660 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4661 }
4662
4663 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4664
4665 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4666 if (err < 0)
4667 goto unlock;
4668
4669 err = new_settings(hdev, sk);
4670 goto unlock;
4671 }
4672
4673 /* Reject disabling when powered on */
4674 if (!cp->val) {
4675 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4676 MGMT_STATUS_REJECTED);
4677 goto unlock;
4678 }
4679
4680 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4681 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4682 MGMT_STATUS_BUSY);
4683 goto unlock;
4684 }
4685
4686 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4687 if (!cmd) {
4688 err = -ENOMEM;
4689 goto unlock;
4690 }
4691
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004692 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004693 * generates the correct flags.
4694 */
4695 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4696
4697 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004698
Johan Hedberg432df052014-08-01 11:13:31 +03004699 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004700 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004701
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004702 /* Since only the advertising data flags will change, there
4703 * is no need to update the scan response data.
4704 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004705 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004706
Johan Hedberg0663ca22013-10-02 13:43:14 +03004707 err = hci_req_run(&req, set_bredr_complete);
4708 if (err < 0)
4709 mgmt_pending_remove(cmd);
4710
4711unlock:
4712 hci_dev_unlock(hdev);
4713 return err;
4714}
4715
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004716static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4717 void *data, u16 len)
4718{
4719 struct mgmt_mode *cp = data;
4720 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004721 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004722 int err;
4723
4724 BT_DBG("request for %s", hdev->name);
4725
Johan Hedberga3209692014-05-26 11:23:35 +03004726 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4727 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004728 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4729 MGMT_STATUS_NOT_SUPPORTED);
4730
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004731 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004732 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4733 MGMT_STATUS_INVALID_PARAMS);
4734
4735 hci_dev_lock(hdev);
4736
Johan Hedberga3209692014-05-26 11:23:35 +03004737 if (!hdev_is_powered(hdev) ||
4738 (!lmp_sc_capable(hdev) &&
4739 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4740 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004741 bool changed;
4742
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004743 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004744 changed = !test_and_set_bit(HCI_SC_ENABLED,
4745 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004746 if (cp->val == 0x02)
4747 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4748 else
4749 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4750 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004751 changed = test_and_clear_bit(HCI_SC_ENABLED,
4752 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004753 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4754 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004755
4756 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4757 if (err < 0)
4758 goto failed;
4759
4760 if (changed)
4761 err = new_settings(hdev, sk);
4762
4763 goto failed;
4764 }
4765
4766 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4767 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4768 MGMT_STATUS_BUSY);
4769 goto failed;
4770 }
4771
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004772 val = !!cp->val;
4773
4774 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4775 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004776 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4777 goto failed;
4778 }
4779
4780 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4781 if (!cmd) {
4782 err = -ENOMEM;
4783 goto failed;
4784 }
4785
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004786 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004787 if (err < 0) {
4788 mgmt_pending_remove(cmd);
4789 goto failed;
4790 }
4791
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004792 if (cp->val == 0x02)
4793 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4794 else
4795 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4796
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004797failed:
4798 hci_dev_unlock(hdev);
4799 return err;
4800}
4801
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004802static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4803 void *data, u16 len)
4804{
4805 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004806 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004807 int err;
4808
4809 BT_DBG("request for %s", hdev->name);
4810
Johan Hedbergb97109792014-06-24 14:00:28 +03004811 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004812 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4813 MGMT_STATUS_INVALID_PARAMS);
4814
4815 hci_dev_lock(hdev);
4816
4817 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004818 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4819 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004820 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004821 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4822 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004823
Johan Hedbergb97109792014-06-24 14:00:28 +03004824 if (cp->val == 0x02)
4825 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4826 &hdev->dev_flags);
4827 else
4828 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4829 &hdev->dev_flags);
4830
4831 if (hdev_is_powered(hdev) && use_changed &&
4832 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4833 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4834 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4835 sizeof(mode), &mode);
4836 }
4837
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004838 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4839 if (err < 0)
4840 goto unlock;
4841
4842 if (changed)
4843 err = new_settings(hdev, sk);
4844
4845unlock:
4846 hci_dev_unlock(hdev);
4847 return err;
4848}
4849
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004850static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4851 u16 len)
4852{
4853 struct mgmt_cp_set_privacy *cp = cp_data;
4854 bool changed;
4855 int err;
4856
4857 BT_DBG("request for %s", hdev->name);
4858
4859 if (!lmp_le_capable(hdev))
4860 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4861 MGMT_STATUS_NOT_SUPPORTED);
4862
4863 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4864 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4865 MGMT_STATUS_INVALID_PARAMS);
4866
4867 if (hdev_is_powered(hdev))
4868 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4869 MGMT_STATUS_REJECTED);
4870
4871 hci_dev_lock(hdev);
4872
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004873 /* If user space supports this command it is also expected to
4874 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4875 */
4876 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4877
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004878 if (cp->privacy) {
4879 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4880 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4881 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4882 } else {
4883 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4884 memset(hdev->irk, 0, sizeof(hdev->irk));
4885 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4886 }
4887
4888 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4889 if (err < 0)
4890 goto unlock;
4891
4892 if (changed)
4893 err = new_settings(hdev, sk);
4894
4895unlock:
4896 hci_dev_unlock(hdev);
4897 return err;
4898}
4899
Johan Hedberg41edf162014-02-18 10:19:35 +02004900static bool irk_is_valid(struct mgmt_irk_info *irk)
4901{
4902 switch (irk->addr.type) {
4903 case BDADDR_LE_PUBLIC:
4904 return true;
4905
4906 case BDADDR_LE_RANDOM:
4907 /* Two most significant bits shall be set */
4908 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4909 return false;
4910 return true;
4911 }
4912
4913 return false;
4914}
4915
4916static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4917 u16 len)
4918{
4919 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004920 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4921 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004922 u16 irk_count, expected_len;
4923 int i, err;
4924
4925 BT_DBG("request for %s", hdev->name);
4926
4927 if (!lmp_le_capable(hdev))
4928 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4929 MGMT_STATUS_NOT_SUPPORTED);
4930
4931 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004932 if (irk_count > max_irk_count) {
4933 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4934 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4935 MGMT_STATUS_INVALID_PARAMS);
4936 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004937
4938 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4939 if (expected_len != len) {
4940 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004941 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004942 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4943 MGMT_STATUS_INVALID_PARAMS);
4944 }
4945
4946 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4947
4948 for (i = 0; i < irk_count; i++) {
4949 struct mgmt_irk_info *key = &cp->irks[i];
4950
4951 if (!irk_is_valid(key))
4952 return cmd_status(sk, hdev->id,
4953 MGMT_OP_LOAD_IRKS,
4954 MGMT_STATUS_INVALID_PARAMS);
4955 }
4956
4957 hci_dev_lock(hdev);
4958
4959 hci_smp_irks_clear(hdev);
4960
4961 for (i = 0; i < irk_count; i++) {
4962 struct mgmt_irk_info *irk = &cp->irks[i];
4963 u8 addr_type;
4964
4965 if (irk->addr.type == BDADDR_LE_PUBLIC)
4966 addr_type = ADDR_LE_DEV_PUBLIC;
4967 else
4968 addr_type = ADDR_LE_DEV_RANDOM;
4969
4970 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4971 BDADDR_ANY);
4972 }
4973
4974 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4975
4976 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4977
4978 hci_dev_unlock(hdev);
4979
4980 return err;
4981}
4982
Johan Hedberg3f706b72013-01-20 14:27:16 +02004983static bool ltk_is_valid(struct mgmt_ltk_info *key)
4984{
4985 if (key->master != 0x00 && key->master != 0x01)
4986 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004987
4988 switch (key->addr.type) {
4989 case BDADDR_LE_PUBLIC:
4990 return true;
4991
4992 case BDADDR_LE_RANDOM:
4993 /* Two most significant bits shall be set */
4994 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4995 return false;
4996 return true;
4997 }
4998
4999 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005000}
5001
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005002static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005003 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005004{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005005 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005006 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5007 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005008 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005009 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005010
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005011 BT_DBG("request for %s", hdev->name);
5012
5013 if (!lmp_le_capable(hdev))
5014 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5015 MGMT_STATUS_NOT_SUPPORTED);
5016
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005017 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005018 if (key_count > max_key_count) {
5019 BT_ERR("load_ltks: too big key_count value %u", key_count);
5020 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5021 MGMT_STATUS_INVALID_PARAMS);
5022 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005023
5024 expected_len = sizeof(*cp) + key_count *
5025 sizeof(struct mgmt_ltk_info);
5026 if (expected_len != len) {
5027 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005028 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005029 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005030 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005031 }
5032
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005033 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005034
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005035 for (i = 0; i < key_count; i++) {
5036 struct mgmt_ltk_info *key = &cp->keys[i];
5037
Johan Hedberg3f706b72013-01-20 14:27:16 +02005038 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005039 return cmd_status(sk, hdev->id,
5040 MGMT_OP_LOAD_LONG_TERM_KEYS,
5041 MGMT_STATUS_INVALID_PARAMS);
5042 }
5043
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005044 hci_dev_lock(hdev);
5045
5046 hci_smp_ltks_clear(hdev);
5047
5048 for (i = 0; i < key_count; i++) {
5049 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005050 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005051
5052 if (key->addr.type == BDADDR_LE_PUBLIC)
5053 addr_type = ADDR_LE_DEV_PUBLIC;
5054 else
5055 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005056
Johan Hedberg61b43352014-05-29 19:36:53 +03005057 switch (key->type) {
5058 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005059 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005060 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005061 break;
5062 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005063 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005064 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005065 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005066 case MGMT_LTK_P256_UNAUTH:
5067 authenticated = 0x00;
5068 type = SMP_LTK_P256;
5069 break;
5070 case MGMT_LTK_P256_AUTH:
5071 authenticated = 0x01;
5072 type = SMP_LTK_P256;
5073 break;
5074 case MGMT_LTK_P256_DEBUG:
5075 authenticated = 0x00;
5076 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005077 default:
5078 continue;
5079 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005080
Johan Hedberg35d70272014-02-19 14:57:47 +02005081 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005082 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005083 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005084 }
5085
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005086 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5087 NULL, 0);
5088
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005089 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005090
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005091 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005092}
5093
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005094static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005095{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005096 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005097 struct mgmt_rp_get_conn_info rp;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005098
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005099 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005100
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005101 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005102 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005103 rp.tx_power = conn->tx_power;
5104 rp.max_tx_power = conn->max_tx_power;
5105 } else {
5106 rp.rssi = HCI_RSSI_INVALID;
5107 rp.tx_power = HCI_TX_POWER_INVALID;
5108 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005109 }
5110
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005111 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5112 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005113
5114 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005115 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005116}
5117
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005118static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005119{
5120 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005121 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005122 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005123 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005124 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005125
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005126 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005127
5128 hci_dev_lock(hdev);
5129
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005130 /* Commands sent in request are either Read RSSI or Read Transmit Power
5131 * Level so we check which one was last sent to retrieve connection
5132 * handle. Both commands have handle as first parameter so it's safe to
5133 * cast data on the same command struct.
5134 *
5135 * First command sent is always Read RSSI and we fail only if it fails.
5136 * In other case we simply override error to indicate success as we
5137 * already remembered if TX power value is actually valid.
5138 */
5139 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5140 if (!cp) {
5141 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005142 status = MGMT_STATUS_SUCCESS;
5143 } else {
5144 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005145 }
5146
5147 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005148 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005149 goto unlock;
5150 }
5151
5152 handle = __le16_to_cpu(cp->handle);
5153 conn = hci_conn_hash_lookup_handle(hdev, handle);
5154 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005155 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005156 goto unlock;
5157 }
5158
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005159 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5160 if (!cmd)
5161 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005162
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005163 cmd->cmd_complete(cmd, status);
5164 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005165
5166unlock:
5167 hci_dev_unlock(hdev);
5168}
5169
5170static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5171 u16 len)
5172{
5173 struct mgmt_cp_get_conn_info *cp = data;
5174 struct mgmt_rp_get_conn_info rp;
5175 struct hci_conn *conn;
5176 unsigned long conn_info_age;
5177 int err = 0;
5178
5179 BT_DBG("%s", hdev->name);
5180
5181 memset(&rp, 0, sizeof(rp));
5182 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5183 rp.addr.type = cp->addr.type;
5184
5185 if (!bdaddr_type_is_valid(cp->addr.type))
5186 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5187 MGMT_STATUS_INVALID_PARAMS,
5188 &rp, sizeof(rp));
5189
5190 hci_dev_lock(hdev);
5191
5192 if (!hdev_is_powered(hdev)) {
5193 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5194 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5195 goto unlock;
5196 }
5197
5198 if (cp->addr.type == BDADDR_BREDR)
5199 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5200 &cp->addr.bdaddr);
5201 else
5202 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5203
5204 if (!conn || conn->state != BT_CONNECTED) {
5205 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5206 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5207 goto unlock;
5208 }
5209
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005210 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5211 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5212 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5213 goto unlock;
5214 }
5215
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005216 /* To avoid client trying to guess when to poll again for information we
5217 * calculate conn info age as random value between min/max set in hdev.
5218 */
5219 conn_info_age = hdev->conn_info_min_age +
5220 prandom_u32_max(hdev->conn_info_max_age -
5221 hdev->conn_info_min_age);
5222
5223 /* Query controller to refresh cached values if they are too old or were
5224 * never read.
5225 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005226 if (time_after(jiffies, conn->conn_info_timestamp +
5227 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005228 !conn->conn_info_timestamp) {
5229 struct hci_request req;
5230 struct hci_cp_read_tx_power req_txp_cp;
5231 struct hci_cp_read_rssi req_rssi_cp;
5232 struct pending_cmd *cmd;
5233
5234 hci_req_init(&req, hdev);
5235 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5236 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5237 &req_rssi_cp);
5238
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005239 /* For LE links TX power does not change thus we don't need to
5240 * query for it once value is known.
5241 */
5242 if (!bdaddr_type_is_le(cp->addr.type) ||
5243 conn->tx_power == HCI_TX_POWER_INVALID) {
5244 req_txp_cp.handle = cpu_to_le16(conn->handle);
5245 req_txp_cp.type = 0x00;
5246 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5247 sizeof(req_txp_cp), &req_txp_cp);
5248 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005249
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005250 /* Max TX power needs to be read only once per connection */
5251 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5252 req_txp_cp.handle = cpu_to_le16(conn->handle);
5253 req_txp_cp.type = 0x01;
5254 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5255 sizeof(req_txp_cp), &req_txp_cp);
5256 }
5257
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005258 err = hci_req_run(&req, conn_info_refresh_complete);
5259 if (err < 0)
5260 goto unlock;
5261
5262 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5263 data, len);
5264 if (!cmd) {
5265 err = -ENOMEM;
5266 goto unlock;
5267 }
5268
5269 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005270 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005271 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005272
5273 conn->conn_info_timestamp = jiffies;
5274 } else {
5275 /* Cache is valid, just reply with values cached in hci_conn */
5276 rp.rssi = conn->rssi;
5277 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005278 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005279
5280 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5281 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5282 }
5283
5284unlock:
5285 hci_dev_unlock(hdev);
5286 return err;
5287}
5288
Johan Hedberg69487372014-12-05 13:36:07 +02005289static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
5290{
5291 struct hci_conn *conn = cmd->user_data;
5292 struct mgmt_rp_get_clock_info rp;
5293 struct hci_dev *hdev;
5294
5295 memset(&rp, 0, sizeof(rp));
5296 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5297
5298 if (status)
5299 goto complete;
5300
5301 hdev = hci_dev_get(cmd->index);
5302 if (hdev) {
5303 rp.local_clock = cpu_to_le32(hdev->clock);
5304 hci_dev_put(hdev);
5305 }
5306
5307 if (conn) {
5308 rp.piconet_clock = cpu_to_le32(conn->clock);
5309 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5310 }
5311
5312complete:
5313 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
5314
5315 if (conn) {
5316 hci_conn_drop(conn);
5317 hci_conn_put(conn);
5318 }
5319}
5320
Johan Hedberg95868422014-06-28 17:54:07 +03005321static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5322{
Johan Hedberg95868422014-06-28 17:54:07 +03005323 struct hci_cp_read_clock *hci_cp;
5324 struct pending_cmd *cmd;
5325 struct hci_conn *conn;
5326
5327 BT_DBG("%s status %u", hdev->name, status);
5328
5329 hci_dev_lock(hdev);
5330
5331 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5332 if (!hci_cp)
5333 goto unlock;
5334
5335 if (hci_cp->which) {
5336 u16 handle = __le16_to_cpu(hci_cp->handle);
5337 conn = hci_conn_hash_lookup_handle(hdev, handle);
5338 } else {
5339 conn = NULL;
5340 }
5341
5342 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5343 if (!cmd)
5344 goto unlock;
5345
Johan Hedberg69487372014-12-05 13:36:07 +02005346 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005347 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005348
5349unlock:
5350 hci_dev_unlock(hdev);
5351}
5352
5353static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5354 u16 len)
5355{
5356 struct mgmt_cp_get_clock_info *cp = data;
5357 struct mgmt_rp_get_clock_info rp;
5358 struct hci_cp_read_clock hci_cp;
5359 struct pending_cmd *cmd;
5360 struct hci_request req;
5361 struct hci_conn *conn;
5362 int err;
5363
5364 BT_DBG("%s", hdev->name);
5365
5366 memset(&rp, 0, sizeof(rp));
5367 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5368 rp.addr.type = cp->addr.type;
5369
5370 if (cp->addr.type != BDADDR_BREDR)
5371 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5372 MGMT_STATUS_INVALID_PARAMS,
5373 &rp, sizeof(rp));
5374
5375 hci_dev_lock(hdev);
5376
5377 if (!hdev_is_powered(hdev)) {
5378 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5379 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5380 goto unlock;
5381 }
5382
5383 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5384 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5385 &cp->addr.bdaddr);
5386 if (!conn || conn->state != BT_CONNECTED) {
5387 err = cmd_complete(sk, hdev->id,
5388 MGMT_OP_GET_CLOCK_INFO,
5389 MGMT_STATUS_NOT_CONNECTED,
5390 &rp, sizeof(rp));
5391 goto unlock;
5392 }
5393 } else {
5394 conn = NULL;
5395 }
5396
5397 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5398 if (!cmd) {
5399 err = -ENOMEM;
5400 goto unlock;
5401 }
5402
Johan Hedberg69487372014-12-05 13:36:07 +02005403 cmd->cmd_complete = clock_info_cmd_complete;
5404
Johan Hedberg95868422014-06-28 17:54:07 +03005405 hci_req_init(&req, hdev);
5406
5407 memset(&hci_cp, 0, sizeof(hci_cp));
5408 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5409
5410 if (conn) {
5411 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005412 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005413
5414 hci_cp.handle = cpu_to_le16(conn->handle);
5415 hci_cp.which = 0x01; /* Piconet clock */
5416 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5417 }
5418
5419 err = hci_req_run(&req, get_clock_info_complete);
5420 if (err < 0)
5421 mgmt_pending_remove(cmd);
5422
5423unlock:
5424 hci_dev_unlock(hdev);
5425 return err;
5426}
5427
Johan Hedberg5a154e62014-12-19 22:26:02 +02005428static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5429{
5430 struct hci_conn *conn;
5431
5432 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5433 if (!conn)
5434 return false;
5435
5436 if (conn->dst_type != type)
5437 return false;
5438
5439 if (conn->state != BT_CONNECTED)
5440 return false;
5441
5442 return true;
5443}
5444
5445/* This function requires the caller holds hdev->lock */
5446static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5447 u8 addr_type, u8 auto_connect)
5448{
5449 struct hci_dev *hdev = req->hdev;
5450 struct hci_conn_params *params;
5451
5452 params = hci_conn_params_add(hdev, addr, addr_type);
5453 if (!params)
5454 return -EIO;
5455
5456 if (params->auto_connect == auto_connect)
5457 return 0;
5458
5459 list_del_init(&params->action);
5460
5461 switch (auto_connect) {
5462 case HCI_AUTO_CONN_DISABLED:
5463 case HCI_AUTO_CONN_LINK_LOSS:
5464 __hci_update_background_scan(req);
5465 break;
5466 case HCI_AUTO_CONN_REPORT:
5467 list_add(&params->action, &hdev->pend_le_reports);
5468 __hci_update_background_scan(req);
5469 break;
5470 case HCI_AUTO_CONN_DIRECT:
5471 case HCI_AUTO_CONN_ALWAYS:
5472 if (!is_connected(hdev, addr, addr_type)) {
5473 list_add(&params->action, &hdev->pend_le_conns);
5474 __hci_update_background_scan(req);
5475 }
5476 break;
5477 }
5478
5479 params->auto_connect = auto_connect;
5480
5481 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5482 auto_connect);
5483
5484 return 0;
5485}
5486
Marcel Holtmann8afef092014-06-29 22:28:34 +02005487static void device_added(struct sock *sk, struct hci_dev *hdev,
5488 bdaddr_t *bdaddr, u8 type, u8 action)
5489{
5490 struct mgmt_ev_device_added ev;
5491
5492 bacpy(&ev.addr.bdaddr, bdaddr);
5493 ev.addr.type = type;
5494 ev.action = action;
5495
5496 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5497}
5498
Johan Hedberg5a154e62014-12-19 22:26:02 +02005499static void add_device_complete(struct hci_dev *hdev, u8 status)
5500{
5501 struct pending_cmd *cmd;
5502
5503 BT_DBG("status 0x%02x", status);
5504
5505 hci_dev_lock(hdev);
5506
5507 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5508 if (!cmd)
5509 goto unlock;
5510
5511 cmd->cmd_complete(cmd, mgmt_status(status));
5512 mgmt_pending_remove(cmd);
5513
5514unlock:
5515 hci_dev_unlock(hdev);
5516}
5517
Marcel Holtmann2faade52014-06-29 19:44:03 +02005518static int add_device(struct sock *sk, struct hci_dev *hdev,
5519 void *data, u16 len)
5520{
5521 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005522 struct pending_cmd *cmd;
5523 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005524 u8 auto_conn, addr_type;
5525 int err;
5526
5527 BT_DBG("%s", hdev->name);
5528
Johan Hedberg66593582014-07-09 12:59:14 +03005529 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005530 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5531 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5532 MGMT_STATUS_INVALID_PARAMS,
5533 &cp->addr, sizeof(cp->addr));
5534
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005535 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005536 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5537 MGMT_STATUS_INVALID_PARAMS,
5538 &cp->addr, sizeof(cp->addr));
5539
Johan Hedberg5a154e62014-12-19 22:26:02 +02005540 hci_req_init(&req, hdev);
5541
Marcel Holtmann2faade52014-06-29 19:44:03 +02005542 hci_dev_lock(hdev);
5543
Johan Hedberg5a154e62014-12-19 22:26:02 +02005544 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5545 if (!cmd) {
5546 err = -ENOMEM;
5547 goto unlock;
5548 }
5549
5550 cmd->cmd_complete = addr_cmd_complete;
5551
Johan Hedberg66593582014-07-09 12:59:14 +03005552 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005553 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005554 if (cp->action != 0x01) {
Johan Hedberg5a154e62014-12-19 22:26:02 +02005555 err = 0;
5556 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5557 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005558 goto unlock;
5559 }
5560
5561 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5562 cp->addr.type);
5563 if (err)
5564 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005565
Johan Hedberg5a154e62014-12-19 22:26:02 +02005566 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005567
Johan Hedberg66593582014-07-09 12:59:14 +03005568 goto added;
5569 }
5570
Marcel Holtmann2faade52014-06-29 19:44:03 +02005571 if (cp->addr.type == BDADDR_LE_PUBLIC)
5572 addr_type = ADDR_LE_DEV_PUBLIC;
5573 else
5574 addr_type = ADDR_LE_DEV_RANDOM;
5575
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005576 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005577 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005578 else if (cp->action == 0x01)
5579 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005580 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005581 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005582
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005583 /* If the connection parameters don't exist for this device,
5584 * they will be created and configured with defaults.
5585 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005586 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005587 auto_conn) < 0) {
Johan Hedberg5a154e62014-12-19 22:26:02 +02005588 err = 0;
5589 cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
5590 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005591 goto unlock;
5592 }
5593
Johan Hedberg66593582014-07-09 12:59:14 +03005594added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005595 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5596
Johan Hedberg5a154e62014-12-19 22:26:02 +02005597 err = hci_req_run(&req, add_device_complete);
5598 if (err < 0) {
5599 /* ENODATA means no HCI commands were needed (e.g. if
5600 * the adapter is powered off).
5601 */
5602 if (err == -ENODATA) {
5603 cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
5604 err = 0;
5605 }
5606 mgmt_pending_remove(cmd);
5607 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005608
5609unlock:
5610 hci_dev_unlock(hdev);
5611 return err;
5612}
5613
Marcel Holtmann8afef092014-06-29 22:28:34 +02005614static void device_removed(struct sock *sk, struct hci_dev *hdev,
5615 bdaddr_t *bdaddr, u8 type)
5616{
5617 struct mgmt_ev_device_removed ev;
5618
5619 bacpy(&ev.addr.bdaddr, bdaddr);
5620 ev.addr.type = type;
5621
5622 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5623}
5624
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005625static void remove_device_complete(struct hci_dev *hdev, u8 status)
5626{
5627 struct pending_cmd *cmd;
5628
5629 BT_DBG("status 0x%02x", status);
5630
5631 hci_dev_lock(hdev);
5632
5633 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5634 if (!cmd)
5635 goto unlock;
5636
5637 cmd->cmd_complete(cmd, mgmt_status(status));
5638 mgmt_pending_remove(cmd);
5639
5640unlock:
5641 hci_dev_unlock(hdev);
5642}
5643
Marcel Holtmann2faade52014-06-29 19:44:03 +02005644static int remove_device(struct sock *sk, struct hci_dev *hdev,
5645 void *data, u16 len)
5646{
5647 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005648 struct pending_cmd *cmd;
5649 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005650 int err;
5651
5652 BT_DBG("%s", hdev->name);
5653
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005654 hci_req_init(&req, hdev);
5655
Marcel Holtmann2faade52014-06-29 19:44:03 +02005656 hci_dev_lock(hdev);
5657
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005658 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5659 if (!cmd) {
5660 err = -ENOMEM;
5661 goto unlock;
5662 }
5663
5664 cmd->cmd_complete = addr_cmd_complete;
5665
Marcel Holtmann2faade52014-06-29 19:44:03 +02005666 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005667 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005668 u8 addr_type;
5669
Johan Hedberg66593582014-07-09 12:59:14 +03005670 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005671 err = 0;
5672 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5673 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005674 goto unlock;
5675 }
5676
Johan Hedberg66593582014-07-09 12:59:14 +03005677 if (cp->addr.type == BDADDR_BREDR) {
5678 err = hci_bdaddr_list_del(&hdev->whitelist,
5679 &cp->addr.bdaddr,
5680 cp->addr.type);
5681 if (err) {
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005682 err = 0;
5683 cmd->cmd_complete(cmd,
5684 MGMT_STATUS_INVALID_PARAMS);
5685 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005686 goto unlock;
5687 }
5688
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005689 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005690
Johan Hedberg66593582014-07-09 12:59:14 +03005691 device_removed(sk, hdev, &cp->addr.bdaddr,
5692 cp->addr.type);
5693 goto complete;
5694 }
5695
Marcel Holtmann2faade52014-06-29 19:44:03 +02005696 if (cp->addr.type == BDADDR_LE_PUBLIC)
5697 addr_type = ADDR_LE_DEV_PUBLIC;
5698 else
5699 addr_type = ADDR_LE_DEV_RANDOM;
5700
Johan Hedbergc71593d2014-07-02 17:37:28 +03005701 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5702 addr_type);
5703 if (!params) {
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005704 err = 0;
5705 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5706 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005707 goto unlock;
5708 }
5709
5710 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005711 err = 0;
5712 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5713 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005714 goto unlock;
5715 }
5716
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005717 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005718 list_del(&params->list);
5719 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005720 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005721
5722 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005723 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005724 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005725 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005726
Marcel Holtmann2faade52014-06-29 19:44:03 +02005727 if (cp->addr.type) {
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005728 err = 0;
5729 cmd->cmd_complete(cmd, MGMT_STATUS_INVALID_PARAMS);
5730 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005731 goto unlock;
5732 }
5733
Johan Hedberg66593582014-07-09 12:59:14 +03005734 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5735 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5736 list_del(&b->list);
5737 kfree(b);
5738 }
5739
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005740 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005741
Johan Hedberg19de0822014-07-06 13:06:51 +03005742 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5743 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5744 continue;
5745 device_removed(sk, hdev, &p->addr, p->addr_type);
5746 list_del(&p->action);
5747 list_del(&p->list);
5748 kfree(p);
5749 }
5750
5751 BT_DBG("All LE connection parameters were removed");
5752
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005753 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005754 }
5755
Johan Hedberg66593582014-07-09 12:59:14 +03005756complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005757 err = hci_req_run(&req, remove_device_complete);
5758 if (err < 0) {
5759 /* ENODATA means no HCI commands were needed (e.g. if
5760 * the adapter is powered off).
5761 */
5762 if (err == -ENODATA) {
5763 cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
5764 err = 0;
5765 }
5766 mgmt_pending_remove(cmd);
5767 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005768
5769unlock:
5770 hci_dev_unlock(hdev);
5771 return err;
5772}
5773
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005774static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5775 u16 len)
5776{
5777 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005778 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5779 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005780 u16 param_count, expected_len;
5781 int i;
5782
5783 if (!lmp_le_capable(hdev))
5784 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5785 MGMT_STATUS_NOT_SUPPORTED);
5786
5787 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005788 if (param_count > max_param_count) {
5789 BT_ERR("load_conn_param: too big param_count value %u",
5790 param_count);
5791 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5792 MGMT_STATUS_INVALID_PARAMS);
5793 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005794
5795 expected_len = sizeof(*cp) + param_count *
5796 sizeof(struct mgmt_conn_param);
5797 if (expected_len != len) {
5798 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5799 expected_len, len);
5800 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5801 MGMT_STATUS_INVALID_PARAMS);
5802 }
5803
5804 BT_DBG("%s param_count %u", hdev->name, param_count);
5805
5806 hci_dev_lock(hdev);
5807
5808 hci_conn_params_clear_disabled(hdev);
5809
5810 for (i = 0; i < param_count; i++) {
5811 struct mgmt_conn_param *param = &cp->params[i];
5812 struct hci_conn_params *hci_param;
5813 u16 min, max, latency, timeout;
5814 u8 addr_type;
5815
5816 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5817 param->addr.type);
5818
5819 if (param->addr.type == BDADDR_LE_PUBLIC) {
5820 addr_type = ADDR_LE_DEV_PUBLIC;
5821 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5822 addr_type = ADDR_LE_DEV_RANDOM;
5823 } else {
5824 BT_ERR("Ignoring invalid connection parameters");
5825 continue;
5826 }
5827
5828 min = le16_to_cpu(param->min_interval);
5829 max = le16_to_cpu(param->max_interval);
5830 latency = le16_to_cpu(param->latency);
5831 timeout = le16_to_cpu(param->timeout);
5832
5833 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5834 min, max, latency, timeout);
5835
5836 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5837 BT_ERR("Ignoring invalid connection parameters");
5838 continue;
5839 }
5840
5841 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5842 addr_type);
5843 if (!hci_param) {
5844 BT_ERR("Failed to add connection parameters");
5845 continue;
5846 }
5847
5848 hci_param->conn_min_interval = min;
5849 hci_param->conn_max_interval = max;
5850 hci_param->conn_latency = latency;
5851 hci_param->supervision_timeout = timeout;
5852 }
5853
5854 hci_dev_unlock(hdev);
5855
5856 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5857}
5858
Marcel Holtmanndbece372014-07-04 18:11:55 +02005859static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5860 void *data, u16 len)
5861{
5862 struct mgmt_cp_set_external_config *cp = data;
5863 bool changed;
5864 int err;
5865
5866 BT_DBG("%s", hdev->name);
5867
5868 if (hdev_is_powered(hdev))
5869 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5870 MGMT_STATUS_REJECTED);
5871
5872 if (cp->config != 0x00 && cp->config != 0x01)
5873 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5874 MGMT_STATUS_INVALID_PARAMS);
5875
5876 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5877 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5878 MGMT_STATUS_NOT_SUPPORTED);
5879
5880 hci_dev_lock(hdev);
5881
5882 if (cp->config)
5883 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5884 &hdev->dev_flags);
5885 else
5886 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5887 &hdev->dev_flags);
5888
5889 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5890 if (err < 0)
5891 goto unlock;
5892
5893 if (!changed)
5894 goto unlock;
5895
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005896 err = new_options(hdev, sk);
5897
Marcel Holtmanndbece372014-07-04 18:11:55 +02005898 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5899 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005900
5901 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5902 set_bit(HCI_CONFIG, &hdev->dev_flags);
5903 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5904
5905 queue_work(hdev->req_workqueue, &hdev->power_on);
5906 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005907 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005908 mgmt_index_added(hdev);
5909 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005910 }
5911
5912unlock:
5913 hci_dev_unlock(hdev);
5914 return err;
5915}
5916
Marcel Holtmann9713c172014-07-06 12:11:15 +02005917static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5918 void *data, u16 len)
5919{
5920 struct mgmt_cp_set_public_address *cp = data;
5921 bool changed;
5922 int err;
5923
5924 BT_DBG("%s", hdev->name);
5925
5926 if (hdev_is_powered(hdev))
5927 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5928 MGMT_STATUS_REJECTED);
5929
5930 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5931 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5932 MGMT_STATUS_INVALID_PARAMS);
5933
5934 if (!hdev->set_bdaddr)
5935 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5936 MGMT_STATUS_NOT_SUPPORTED);
5937
5938 hci_dev_lock(hdev);
5939
5940 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5941 bacpy(&hdev->public_addr, &cp->bdaddr);
5942
5943 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5944 if (err < 0)
5945 goto unlock;
5946
5947 if (!changed)
5948 goto unlock;
5949
5950 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5951 err = new_options(hdev, sk);
5952
5953 if (is_configured(hdev)) {
5954 mgmt_index_removed(hdev);
5955
5956 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5957
5958 set_bit(HCI_CONFIG, &hdev->dev_flags);
5959 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5960
5961 queue_work(hdev->req_workqueue, &hdev->power_on);
5962 }
5963
5964unlock:
5965 hci_dev_unlock(hdev);
5966 return err;
5967}
5968
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005969static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005970 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5971 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005972 bool var_len;
5973 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005974} mgmt_handlers[] = {
5975 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005976 { read_version, false, MGMT_READ_VERSION_SIZE },
5977 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5978 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5979 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5980 { set_powered, false, MGMT_SETTING_SIZE },
5981 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5982 { set_connectable, false, MGMT_SETTING_SIZE },
5983 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005984 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005985 { set_link_security, false, MGMT_SETTING_SIZE },
5986 { set_ssp, false, MGMT_SETTING_SIZE },
5987 { set_hs, false, MGMT_SETTING_SIZE },
5988 { set_le, false, MGMT_SETTING_SIZE },
5989 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5990 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5991 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5992 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5993 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5994 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5995 { disconnect, false, MGMT_DISCONNECT_SIZE },
5996 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5997 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5998 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5999 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6000 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6001 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6002 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6003 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6004 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6005 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6006 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6007 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006008 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006009 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6010 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6011 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6012 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6013 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6014 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006015 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006016 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006017 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006018 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006019 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006020 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006021 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006022 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006023 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006024 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006025 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006026 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6027 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006028 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6029 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006030 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006031 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006032 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006033 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006034};
6035
Johan Hedberg03811012010-12-08 00:21:06 +02006036int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6037{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006038 void *buf;
6039 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006040 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006041 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006042 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006043 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006044 int err;
6045
6046 BT_DBG("got %zu bytes", msglen);
6047
6048 if (msglen < sizeof(*hdr))
6049 return -EINVAL;
6050
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006051 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006052 if (!buf)
6053 return -ENOMEM;
6054
Al Viro6ce8e9c2014-04-06 21:25:44 -04006055 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006056 err = -EFAULT;
6057 goto done;
6058 }
6059
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006060 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006061 opcode = __le16_to_cpu(hdr->opcode);
6062 index = __le16_to_cpu(hdr->index);
6063 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006064
6065 if (len != msglen - sizeof(*hdr)) {
6066 err = -EINVAL;
6067 goto done;
6068 }
6069
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006070 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006071 hdev = hci_dev_get(index);
6072 if (!hdev) {
6073 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006074 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006075 goto done;
6076 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006077
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006078 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02006079 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006080 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006081 err = cmd_status(sk, index, opcode,
6082 MGMT_STATUS_INVALID_INDEX);
6083 goto done;
6084 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006085
6086 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006087 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006088 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6089 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006090 err = cmd_status(sk, index, opcode,
6091 MGMT_STATUS_INVALID_INDEX);
6092 goto done;
6093 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006094 }
6095
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006096 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006097 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006098 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006099 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006100 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006101 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006102 }
6103
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006104 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6105 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6106 err = cmd_status(sk, index, opcode,
6107 MGMT_STATUS_INVALID_INDEX);
6108 goto done;
6109 }
6110
6111 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6112 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006113 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006114 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006115 goto done;
6116 }
6117
Johan Hedbergbe22b542012-03-01 22:24:41 +02006118 handler = &mgmt_handlers[opcode];
6119
6120 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006121 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006122 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006123 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006124 goto done;
6125 }
6126
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006127 if (hdev)
6128 mgmt_init_hdev(sk, hdev);
6129
6130 cp = buf + sizeof(*hdr);
6131
Johan Hedbergbe22b542012-03-01 22:24:41 +02006132 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006133 if (err < 0)
6134 goto done;
6135
Johan Hedberg03811012010-12-08 00:21:06 +02006136 err = msglen;
6137
6138done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006139 if (hdev)
6140 hci_dev_put(hdev);
6141
Johan Hedberg03811012010-12-08 00:21:06 +02006142 kfree(buf);
6143 return err;
6144}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006145
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006146void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006147{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006148 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006149 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006150
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006151 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6152 return;
6153
6154 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6155 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6156 else
6157 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006158}
6159
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006160void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006161{
Johan Hedberg5f159032012-03-02 03:13:19 +02006162 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006163
Marcel Holtmann1514b892013-10-06 08:25:01 -07006164 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006165 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006166
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006167 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6168 return;
6169
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006170 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006171
Marcel Holtmannedd38962014-07-02 21:30:55 +02006172 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6173 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6174 else
6175 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006176}
6177
Andre Guedes6046dc32014-02-26 20:21:51 -03006178/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006179static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006180{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006181 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006182 struct hci_conn_params *p;
6183
6184 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006185 /* Needed for AUTO_OFF case where might not "really"
6186 * have been powered off.
6187 */
6188 list_del_init(&p->action);
6189
6190 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006191 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006192 case HCI_AUTO_CONN_ALWAYS:
6193 list_add(&p->action, &hdev->pend_le_conns);
6194 break;
6195 case HCI_AUTO_CONN_REPORT:
6196 list_add(&p->action, &hdev->pend_le_reports);
6197 break;
6198 default:
6199 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006200 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006201 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006202
Johan Hedberg2cf22212014-12-19 22:26:00 +02006203 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006204}
6205
Johan Hedberg229ab392013-03-15 17:06:53 -05006206static void powered_complete(struct hci_dev *hdev, u8 status)
6207{
6208 struct cmd_lookup match = { NULL, hdev };
6209
6210 BT_DBG("status 0x%02x", status);
6211
6212 hci_dev_lock(hdev);
6213
6214 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6215
6216 new_settings(hdev, match.sk);
6217
6218 hci_dev_unlock(hdev);
6219
6220 if (match.sk)
6221 sock_put(match.sk);
6222}
6223
Johan Hedberg70da6242013-03-15 17:06:51 -05006224static int powered_update_hci(struct hci_dev *hdev)
6225{
Johan Hedberg890ea892013-03-15 17:06:52 -05006226 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006227 u8 link_sec;
6228
Johan Hedberg890ea892013-03-15 17:06:52 -05006229 hci_req_init(&req, hdev);
6230
Johan Hedberg70da6242013-03-15 17:06:51 -05006231 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6232 !lmp_host_ssp_capable(hdev)) {
6233 u8 ssp = 1;
6234
Johan Hedberg890ea892013-03-15 17:06:52 -05006235 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006236 }
6237
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006238 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6239 u8 sc = 0x01;
6240 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
6241 }
6242
Johan Hedbergc73eee92013-04-19 18:35:21 +03006243 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6244 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006245 struct hci_cp_write_le_host_supported cp;
6246
Marcel Holtmann32226e42014-07-24 20:04:16 +02006247 cp.le = 0x01;
6248 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006249
6250 /* Check first if we already have the right
6251 * host state (host features set)
6252 */
6253 if (cp.le != lmp_host_le_capable(hdev) ||
6254 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006255 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6256 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006257 }
6258
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006259 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006260 /* Make sure the controller has a good default for
6261 * advertising data. This also applies to the case
6262 * where BR/EDR was toggled during the AUTO_OFF phase.
6263 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006264 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006265 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006266 update_scan_rsp_data(&req);
6267 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006268
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006269 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6270 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006271
6272 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006273 }
6274
Johan Hedberg70da6242013-03-15 17:06:51 -05006275 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6276 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006277 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6278 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006279
6280 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006281 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006282 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006283 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006284 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006285 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006286 }
6287
Johan Hedberg229ab392013-03-15 17:06:53 -05006288 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006289}
6290
Johan Hedberg744cf192011-11-08 20:40:14 +02006291int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006292{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006293 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006294 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006295 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006296
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006297 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6298 return 0;
6299
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006300 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006301 if (powered_update_hci(hdev) == 0)
6302 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006303
Johan Hedberg229ab392013-03-15 17:06:53 -05006304 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6305 &match);
6306 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006307 }
6308
Johan Hedberg229ab392013-03-15 17:06:53 -05006309 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006310
6311 /* If the power off is because of hdev unregistration let
6312 * use the appropriate INVALID_INDEX status. Otherwise use
6313 * NOT_POWERED. We cover both scenarios here since later in
6314 * mgmt_index_removed() any hci_conn callbacks will have already
6315 * been triggered, potentially causing misleading DISCONNECTED
6316 * status responses.
6317 */
6318 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6319 status = MGMT_STATUS_INVALID_INDEX;
6320 else
6321 status = MGMT_STATUS_NOT_POWERED;
6322
6323 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006324
6325 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6326 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6327 zero_cod, sizeof(zero_cod), NULL);
6328
6329new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006330 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006331
6332 if (match.sk)
6333 sock_put(match.sk);
6334
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006335 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006336}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006337
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006338void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006339{
6340 struct pending_cmd *cmd;
6341 u8 status;
6342
6343 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6344 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006345 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006346
6347 if (err == -ERFKILL)
6348 status = MGMT_STATUS_RFKILLED;
6349 else
6350 status = MGMT_STATUS_FAILED;
6351
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006352 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006353
6354 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006355}
6356
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006357void mgmt_discoverable_timeout(struct hci_dev *hdev)
6358{
6359 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006360
6361 hci_dev_lock(hdev);
6362
6363 /* When discoverable timeout triggers, then just make sure
6364 * the limited discoverable flag is cleared. Even in the case
6365 * of a timeout triggered from general discoverable, it is
6366 * safe to unconditionally clear the flag.
6367 */
6368 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006369 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006370
6371 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006372 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6373 u8 scan = SCAN_PAGE;
6374 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6375 sizeof(scan), &scan);
6376 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006377 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006378 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006379 hci_req_run(&req, NULL);
6380
6381 hdev->discov_timeout = 0;
6382
Johan Hedberg9a43e252013-10-20 19:00:07 +03006383 new_settings(hdev, NULL);
6384
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006385 hci_dev_unlock(hdev);
6386}
6387
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006388void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6389 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006390{
Johan Hedberg86742e12011-11-07 23:13:38 +02006391 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006392
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006393 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006394
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006395 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006396 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006397 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006398 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006399 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006400 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006401
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006402 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006403}
Johan Hedbergf7520542011-01-20 12:34:39 +02006404
Johan Hedbergd7b25452014-05-23 13:19:53 +03006405static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6406{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006407 switch (ltk->type) {
6408 case SMP_LTK:
6409 case SMP_LTK_SLAVE:
6410 if (ltk->authenticated)
6411 return MGMT_LTK_AUTHENTICATED;
6412 return MGMT_LTK_UNAUTHENTICATED;
6413 case SMP_LTK_P256:
6414 if (ltk->authenticated)
6415 return MGMT_LTK_P256_AUTH;
6416 return MGMT_LTK_P256_UNAUTH;
6417 case SMP_LTK_P256_DEBUG:
6418 return MGMT_LTK_P256_DEBUG;
6419 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006420
6421 return MGMT_LTK_UNAUTHENTICATED;
6422}
6423
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006424void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006425{
6426 struct mgmt_ev_new_long_term_key ev;
6427
6428 memset(&ev, 0, sizeof(ev));
6429
Marcel Holtmann5192d302014-02-19 17:11:58 -08006430 /* Devices using resolvable or non-resolvable random addresses
6431 * without providing an indentity resolving key don't require
6432 * to store long term keys. Their addresses will change the
6433 * next time around.
6434 *
6435 * Only when a remote device provides an identity address
6436 * make sure the long term key is stored. If the remote
6437 * identity is known, the long term keys are internally
6438 * mapped to the identity address. So allow static random
6439 * and public addresses here.
6440 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006441 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6442 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6443 ev.store_hint = 0x00;
6444 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006445 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006446
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006447 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006448 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006449 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006450 ev.key.enc_size = key->enc_size;
6451 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006452 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006453
Johan Hedberg2ceba532014-06-16 19:25:16 +03006454 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006455 ev.key.master = 1;
6456
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006457 memcpy(ev.key.val, key->val, sizeof(key->val));
6458
Marcel Holtmann083368f2013-10-15 14:26:29 -07006459 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006460}
6461
Johan Hedberg95fbac82014-02-19 15:18:31 +02006462void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6463{
6464 struct mgmt_ev_new_irk ev;
6465
6466 memset(&ev, 0, sizeof(ev));
6467
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006468 /* For identity resolving keys from devices that are already
6469 * using a public address or static random address, do not
6470 * ask for storing this key. The identity resolving key really
6471 * is only mandatory for devices using resovlable random
6472 * addresses.
6473 *
6474 * Storing all identity resolving keys has the downside that
6475 * they will be also loaded on next boot of they system. More
6476 * identity resolving keys, means more time during scanning is
6477 * needed to actually resolve these addresses.
6478 */
6479 if (bacmp(&irk->rpa, BDADDR_ANY))
6480 ev.store_hint = 0x01;
6481 else
6482 ev.store_hint = 0x00;
6483
Johan Hedberg95fbac82014-02-19 15:18:31 +02006484 bacpy(&ev.rpa, &irk->rpa);
6485 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6486 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6487 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6488
6489 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6490}
6491
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006492void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6493 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006494{
6495 struct mgmt_ev_new_csrk ev;
6496
6497 memset(&ev, 0, sizeof(ev));
6498
6499 /* Devices using resolvable or non-resolvable random addresses
6500 * without providing an indentity resolving key don't require
6501 * to store signature resolving keys. Their addresses will change
6502 * the next time around.
6503 *
6504 * Only when a remote device provides an identity address
6505 * make sure the signature resolving key is stored. So allow
6506 * static random and public addresses here.
6507 */
6508 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6509 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6510 ev.store_hint = 0x00;
6511 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006512 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006513
6514 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6515 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6516 ev.key.master = csrk->master;
6517 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6518
6519 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6520}
6521
Andre Guedesffb5a8272014-07-01 18:10:11 -03006522void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006523 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6524 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006525{
6526 struct mgmt_ev_new_conn_param ev;
6527
Johan Hedbergc103aea2014-07-02 17:37:34 +03006528 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6529 return;
6530
Andre Guedesffb5a8272014-07-01 18:10:11 -03006531 memset(&ev, 0, sizeof(ev));
6532 bacpy(&ev.addr.bdaddr, bdaddr);
6533 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006534 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006535 ev.min_interval = cpu_to_le16(min_interval);
6536 ev.max_interval = cpu_to_le16(max_interval);
6537 ev.latency = cpu_to_le16(latency);
6538 ev.timeout = cpu_to_le16(timeout);
6539
6540 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6541}
6542
Marcel Holtmann94933992013-10-15 10:26:39 -07006543static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6544 u8 data_len)
6545{
6546 eir[eir_len++] = sizeof(type) + data_len;
6547 eir[eir_len++] = type;
6548 memcpy(&eir[eir_len], data, data_len);
6549 eir_len += data_len;
6550
6551 return eir_len;
6552}
6553
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006554void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6555 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006556{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006557 char buf[512];
6558 struct mgmt_ev_device_connected *ev = (void *) buf;
6559 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006560
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006561 bacpy(&ev->addr.bdaddr, &conn->dst);
6562 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006563
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006564 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006565
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006566 /* We must ensure that the EIR Data fields are ordered and
6567 * unique. Keep it simple for now and avoid the problem by not
6568 * adding any BR/EDR data to the LE adv.
6569 */
6570 if (conn->le_adv_data_len > 0) {
6571 memcpy(&ev->eir[eir_len],
6572 conn->le_adv_data, conn->le_adv_data_len);
6573 eir_len = conn->le_adv_data_len;
6574 } else {
6575 if (name_len > 0)
6576 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6577 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006578
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006579 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006580 eir_len = eir_append_data(ev->eir, eir_len,
6581 EIR_CLASS_OF_DEV,
6582 conn->dev_class, 3);
6583 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006584
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006585 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006586
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006587 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6588 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006589}
6590
Johan Hedberg8962ee72011-01-20 12:40:27 +02006591static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6592{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006593 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006594
Johan Hedbergf5818c22014-12-05 13:36:02 +02006595 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006596
6597 *sk = cmd->sk;
6598 sock_hold(*sk);
6599
Johan Hedberga664b5b2011-02-19 12:06:02 -03006600 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006601}
6602
Johan Hedberg124f6e32012-02-09 13:50:12 +02006603static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006604{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006605 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006606 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006607
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006608 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6609
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006610 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006611 mgmt_pending_remove(cmd);
6612}
6613
Johan Hedberg84c61d92014-08-01 11:13:30 +03006614bool mgmt_powering_down(struct hci_dev *hdev)
6615{
6616 struct pending_cmd *cmd;
6617 struct mgmt_mode *cp;
6618
6619 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6620 if (!cmd)
6621 return false;
6622
6623 cp = cmd->param;
6624 if (!cp->val)
6625 return true;
6626
6627 return false;
6628}
6629
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006630void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006631 u8 link_type, u8 addr_type, u8 reason,
6632 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006633{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006634 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006635 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006636
Johan Hedberg84c61d92014-08-01 11:13:30 +03006637 /* The connection is still in hci_conn_hash so test for 1
6638 * instead of 0 to know if this is the last one.
6639 */
6640 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6641 cancel_delayed_work(&hdev->power_off);
6642 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006643 }
6644
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006645 if (!mgmt_connected)
6646 return;
6647
Andre Guedes57eb7762013-10-30 19:01:41 -03006648 if (link_type != ACL_LINK && link_type != LE_LINK)
6649 return;
6650
Johan Hedberg744cf192011-11-08 20:40:14 +02006651 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006652
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006653 bacpy(&ev.addr.bdaddr, bdaddr);
6654 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6655 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006656
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006657 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006658
6659 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006660 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006661
Johan Hedberg124f6e32012-02-09 13:50:12 +02006662 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006663 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006664}
6665
Marcel Holtmann78929242013-10-06 23:55:47 -07006666void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6667 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006668{
Andre Guedes3655bba2013-10-30 19:01:40 -03006669 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6670 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006671 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006672
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006673 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6674 hdev);
6675
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006676 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006677 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006678 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006679
Andre Guedes3655bba2013-10-30 19:01:40 -03006680 cp = cmd->param;
6681
6682 if (bacmp(bdaddr, &cp->addr.bdaddr))
6683 return;
6684
6685 if (cp->addr.type != bdaddr_type)
6686 return;
6687
Johan Hedbergf5818c22014-12-05 13:36:02 +02006688 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006689 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006690}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006691
Marcel Holtmann445608d2013-10-06 23:55:48 -07006692void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6693 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006694{
6695 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006696
Johan Hedberg84c61d92014-08-01 11:13:30 +03006697 /* The connection is still in hci_conn_hash so test for 1
6698 * instead of 0 to know if this is the last one.
6699 */
6700 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6701 cancel_delayed_work(&hdev->power_off);
6702 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006703 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006704
Johan Hedberg4c659c32011-11-07 23:13:39 +02006705 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006706 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006707 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006708
Marcel Holtmann445608d2013-10-06 23:55:48 -07006709 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006710}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006711
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006712void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006713{
6714 struct mgmt_ev_pin_code_request ev;
6715
Johan Hedbergd8457692012-02-17 14:24:57 +02006716 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006717 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006718 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006719
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006720 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006721}
6722
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006723void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6724 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006725{
6726 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006727
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006728 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006729 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006730 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006731
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006732 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006733 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006734}
6735
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006736void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6737 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006738{
6739 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006740
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006741 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006742 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006743 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006744
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006745 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006746 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006747}
Johan Hedberga5c29682011-02-19 12:05:57 -03006748
Johan Hedberg744cf192011-11-08 20:40:14 +02006749int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006750 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006751 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006752{
6753 struct mgmt_ev_user_confirm_request ev;
6754
Johan Hedberg744cf192011-11-08 20:40:14 +02006755 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006756
Johan Hedberg272d90d2012-02-09 15:26:12 +02006757 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006758 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006759 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006760 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006761
Johan Hedberg744cf192011-11-08 20:40:14 +02006762 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006763 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006764}
6765
Johan Hedberg272d90d2012-02-09 15:26:12 +02006766int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006767 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006768{
6769 struct mgmt_ev_user_passkey_request ev;
6770
6771 BT_DBG("%s", hdev->name);
6772
Johan Hedberg272d90d2012-02-09 15:26:12 +02006773 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006774 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006775
6776 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006777 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006778}
6779
Brian Gix0df4c182011-11-16 13:53:13 -08006780static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006781 u8 link_type, u8 addr_type, u8 status,
6782 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006783{
6784 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006785
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006786 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006787 if (!cmd)
6788 return -ENOENT;
6789
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006790 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006791 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006792
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006793 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006794}
6795
Johan Hedberg744cf192011-11-08 20:40:14 +02006796int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006797 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006798{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006799 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006800 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006801}
6802
Johan Hedberg272d90d2012-02-09 15:26:12 +02006803int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006804 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006805{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006806 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006807 status,
6808 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006809}
Johan Hedberg2a611692011-02-19 12:06:00 -03006810
Brian Gix604086b2011-11-23 08:28:33 -08006811int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006812 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006813{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006814 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006815 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006816}
6817
Johan Hedberg272d90d2012-02-09 15:26:12 +02006818int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006819 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006820{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006821 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006822 status,
6823 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006824}
6825
Johan Hedberg92a25252012-09-06 18:39:26 +03006826int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6827 u8 link_type, u8 addr_type, u32 passkey,
6828 u8 entered)
6829{
6830 struct mgmt_ev_passkey_notify ev;
6831
6832 BT_DBG("%s", hdev->name);
6833
6834 bacpy(&ev.addr.bdaddr, bdaddr);
6835 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6836 ev.passkey = __cpu_to_le32(passkey);
6837 ev.entered = entered;
6838
6839 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6840}
6841
Johan Hedberge1e930f2014-09-08 17:09:49 -07006842void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006843{
6844 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006845 struct pending_cmd *cmd;
6846 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006847
Johan Hedberge1e930f2014-09-08 17:09:49 -07006848 bacpy(&ev.addr.bdaddr, &conn->dst);
6849 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6850 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006851
Johan Hedberge1e930f2014-09-08 17:09:49 -07006852 cmd = find_pairing(conn);
6853
6854 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6855 cmd ? cmd->sk : NULL);
6856
Johan Hedberga511b352014-12-11 21:45:45 +02006857 if (cmd) {
6858 cmd->cmd_complete(cmd, status);
6859 mgmt_pending_remove(cmd);
6860 }
Johan Hedberg2a611692011-02-19 12:06:00 -03006861}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006862
Marcel Holtmann464996a2013-10-15 14:26:24 -07006863void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006864{
6865 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006866 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006867
6868 if (status) {
6869 u8 mgmt_err = mgmt_status(status);
6870 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006871 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006872 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006873 }
6874
Marcel Holtmann464996a2013-10-15 14:26:24 -07006875 if (test_bit(HCI_AUTH, &hdev->flags))
6876 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6877 &hdev->dev_flags);
6878 else
6879 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6880 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006881
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006882 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006883 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006884
Johan Hedberg47990ea2012-02-22 11:58:37 +02006885 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006886 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006887
6888 if (match.sk)
6889 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006890}
6891
Johan Hedberg890ea892013-03-15 17:06:52 -05006892static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006893{
Johan Hedberg890ea892013-03-15 17:06:52 -05006894 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006895 struct hci_cp_write_eir cp;
6896
Johan Hedberg976eb202012-10-24 21:12:01 +03006897 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006898 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006899
Johan Hedbergc80da272012-02-22 15:38:48 +02006900 memset(hdev->eir, 0, sizeof(hdev->eir));
6901
Johan Hedbergcacaf522012-02-21 00:52:42 +02006902 memset(&cp, 0, sizeof(cp));
6903
Johan Hedberg890ea892013-03-15 17:06:52 -05006904 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006905}
6906
Marcel Holtmann3e248562013-10-15 14:26:25 -07006907void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006908{
6909 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006910 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006911 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006912
6913 if (status) {
6914 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006915
6916 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006917 &hdev->dev_flags)) {
6918 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006919 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006920 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006921
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006922 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6923 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006924 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006925 }
6926
6927 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006928 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006929 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006930 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6931 if (!changed)
6932 changed = test_and_clear_bit(HCI_HS_ENABLED,
6933 &hdev->dev_flags);
6934 else
6935 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006936 }
6937
6938 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6939
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006940 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006941 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006942
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006943 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006944 sock_put(match.sk);
6945
Johan Hedberg890ea892013-03-15 17:06:52 -05006946 hci_req_init(&req, hdev);
6947
Johan Hedberg37699722014-06-24 14:00:27 +03006948 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6949 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6950 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6951 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006952 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006953 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006954 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006955 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006956
6957 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006958}
6959
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006960void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6961{
6962 struct cmd_lookup match = { NULL, hdev };
6963 bool changed = false;
6964
6965 if (status) {
6966 u8 mgmt_err = mgmt_status(status);
6967
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006968 if (enable) {
6969 if (test_and_clear_bit(HCI_SC_ENABLED,
6970 &hdev->dev_flags))
6971 new_settings(hdev, NULL);
6972 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6973 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006974
6975 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6976 cmd_status_rsp, &mgmt_err);
6977 return;
6978 }
6979
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006980 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006981 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006982 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006983 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006984 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6985 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006986
6987 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6988 settings_rsp, &match);
6989
6990 if (changed)
6991 new_settings(hdev, match.sk);
6992
6993 if (match.sk)
6994 sock_put(match.sk);
6995}
6996
Johan Hedberg92da6092013-03-15 17:06:55 -05006997static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006998{
6999 struct cmd_lookup *match = data;
7000
Johan Hedberg90e70452012-02-23 23:09:40 +02007001 if (match->sk == NULL) {
7002 match->sk = cmd->sk;
7003 sock_hold(match->sk);
7004 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007005}
7006
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007007void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7008 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007009{
Johan Hedberg90e70452012-02-23 23:09:40 +02007010 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007011
Johan Hedberg92da6092013-03-15 17:06:55 -05007012 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7013 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7014 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007015
7016 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007017 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7018 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007019
7020 if (match.sk)
7021 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007022}
7023
Marcel Holtmann7667da32013-10-15 14:26:27 -07007024void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007025{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007026 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007027 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007028
Johan Hedberg13928972013-03-15 17:07:00 -05007029 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007030 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007031
7032 memset(&ev, 0, sizeof(ev));
7033 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007034 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007035
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007036 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007037 if (!cmd) {
7038 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007039
Johan Hedberg13928972013-03-15 17:07:00 -05007040 /* If this is a HCI command related to powering on the
7041 * HCI dev don't send any mgmt signals.
7042 */
7043 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007044 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007045 }
7046
Marcel Holtmann7667da32013-10-15 14:26:27 -07007047 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7048 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007049}
Szymon Jancc35938b2011-03-22 13:12:21 +01007050
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007051void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007052 u8 *rand192, u8 *hash256, u8 *rand256,
7053 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007054{
7055 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007056
Johan Hedberg744cf192011-11-08 20:40:14 +02007057 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007058
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007059 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007060 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007061 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007062
7063 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007064 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7065 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007066 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03007067 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007068 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01007069
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007070 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02007071 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01007072
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007073 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007074 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007075
7076 cmd_complete(cmd->sk, hdev->id,
7077 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7078 &rp, sizeof(rp));
7079 } else {
7080 struct mgmt_rp_read_local_oob_data rp;
7081
7082 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02007083 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007084
7085 cmd_complete(cmd->sk, hdev->id,
7086 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7087 &rp, sizeof(rp));
7088 }
Szymon Jancc35938b2011-03-22 13:12:21 +01007089 }
7090
7091 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007092}
Johan Hedberge17acd42011-03-30 23:57:16 +03007093
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007094static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7095{
7096 int i;
7097
7098 for (i = 0; i < uuid_count; i++) {
7099 if (!memcmp(uuid, uuids[i], 16))
7100 return true;
7101 }
7102
7103 return false;
7104}
7105
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007106static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7107{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007108 u16 parsed = 0;
7109
7110 while (parsed < eir_len) {
7111 u8 field_len = eir[0];
7112 u8 uuid[16];
7113 int i;
7114
7115 if (field_len == 0)
7116 break;
7117
7118 if (eir_len - parsed < field_len + 1)
7119 break;
7120
7121 switch (eir[1]) {
7122 case EIR_UUID16_ALL:
7123 case EIR_UUID16_SOME:
7124 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007125 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007126 uuid[13] = eir[i + 3];
7127 uuid[12] = eir[i + 2];
7128 if (has_uuid(uuid, uuid_count, uuids))
7129 return true;
7130 }
7131 break;
7132 case EIR_UUID32_ALL:
7133 case EIR_UUID32_SOME:
7134 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007135 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007136 uuid[15] = eir[i + 5];
7137 uuid[14] = eir[i + 4];
7138 uuid[13] = eir[i + 3];
7139 uuid[12] = eir[i + 2];
7140 if (has_uuid(uuid, uuid_count, uuids))
7141 return true;
7142 }
7143 break;
7144 case EIR_UUID128_ALL:
7145 case EIR_UUID128_SOME:
7146 for (i = 0; i + 17 <= field_len; i += 16) {
7147 memcpy(uuid, eir + i + 2, 16);
7148 if (has_uuid(uuid, uuid_count, uuids))
7149 return true;
7150 }
7151 break;
7152 }
7153
7154 parsed += field_len + 1;
7155 eir += field_len + 1;
7156 }
7157
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007158 return false;
7159}
7160
Marcel Holtmann901801b2013-10-06 23:55:51 -07007161void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007162 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7163 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007164{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007165 char buf[512];
7166 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007167 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007168 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007169
Johan Hedberg75ce2082014-07-02 22:42:01 +03007170 /* Don't send events for a non-kernel initiated discovery. With
7171 * LE one exception is if we have pend_le_reports > 0 in which
7172 * case we're doing passive scanning and want these events.
7173 */
7174 if (!hci_discovery_active(hdev)) {
7175 if (link_type == ACL_LINK)
7176 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007177 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007178 return;
7179 }
Andre Guedes12602d02013-04-30 15:29:40 -03007180
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007181 /* When using service discovery with a RSSI threshold, then check
7182 * if such a RSSI threshold is specified. If a RSSI threshold has
7183 * been specified, then all results with a RSSI smaller than the
7184 * RSSI threshold will be dropped.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007185 *
7186 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7187 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007188 */
7189 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Marcel Holtmannefb25132014-12-05 13:03:34 +01007190 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007191 return;
7192
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007193 /* Make sure that the buffer is big enough. The 5 extra bytes
7194 * are for the potential CoD field.
7195 */
7196 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007197 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007198
Johan Hedberg1dc06092012-01-15 21:01:23 +02007199 memset(buf, 0, sizeof(buf));
7200
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007201 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7202 * RSSI value was reported as 0 when not available. This behavior
7203 * is kept when using device discovery. This is required for full
7204 * backwards compatibility with the API.
7205 *
7206 * However when using service discovery, the value 127 will be
7207 * returned when the RSSI is not available.
7208 */
7209 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007210 rssi = 0;
7211
Johan Hedberg841c5642014-07-07 12:45:54 +03007212 bacpy(&ev->addr.bdaddr, bdaddr);
7213 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007214 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007215 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007216
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007217 if (eir_len > 0) {
7218 /* When using service discovery and a list of UUID is
7219 * provided, results with no matching UUID should be
7220 * dropped. In case there is a match the result is
7221 * kept and checking possible scan response data
7222 * will be skipped.
7223 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007224 if (hdev->discovery.uuid_count > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007225 match = eir_has_uuids(eir, eir_len,
7226 hdev->discovery.uuid_count,
7227 hdev->discovery.uuids);
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007228 else
7229 match = true;
7230
7231 if (!match && !scan_rsp_len)
7232 return;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007233
7234 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007235 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007236 } else {
7237 /* When using service discovery and a list of UUID is
7238 * provided, results with empty EIR or advertising data
7239 * should be dropped since they do not match any UUID.
7240 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007241 if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007242 return;
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007243
7244 match = false;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007245 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007246
Johan Hedberg1dc06092012-01-15 21:01:23 +02007247 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7248 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007249 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007250
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007251 if (scan_rsp_len > 0) {
7252 /* When using service discovery and a list of UUID is
7253 * provided, results with no matching UUID should be
7254 * dropped if there is no previous match from the
7255 * advertising data.
7256 */
7257 if (hdev->discovery.uuid_count > 0) {
7258 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7259 hdev->discovery.uuid_count,
7260 hdev->discovery.uuids))
7261 return;
7262 }
7263
7264 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007265 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007266 } else {
7267 /* When using service discovery and a list of UUID is
7268 * provided, results with empty scan response and no
7269 * previous matched advertising data should be dropped.
7270 */
7271 if (hdev->discovery.uuid_count > 0 && !match)
7272 return;
7273 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007274
7275 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7276 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007277
Marcel Holtmann901801b2013-10-06 23:55:51 -07007278 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007279}
Johan Hedberga88a9652011-03-30 13:18:12 +03007280
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007281void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7282 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007283{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007284 struct mgmt_ev_device_found *ev;
7285 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7286 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007287
Johan Hedbergb644ba32012-01-17 21:48:47 +02007288 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007289
Johan Hedbergb644ba32012-01-17 21:48:47 +02007290 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007291
Johan Hedbergb644ba32012-01-17 21:48:47 +02007292 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007293 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007294 ev->rssi = rssi;
7295
7296 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007297 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007298
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007299 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007300
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007301 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007302}
Johan Hedberg314b2382011-04-27 10:29:57 -04007303
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007304void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007305{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007306 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007307
Andre Guedes343fb142011-11-22 17:14:19 -03007308 BT_DBG("%s discovering %u", hdev->name, discovering);
7309
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007310 memset(&ev, 0, sizeof(ev));
7311 ev.type = hdev->discovery.type;
7312 ev.discovering = discovering;
7313
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007314 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007315}
Antti Julku5e762442011-08-25 16:48:02 +03007316
Marcel Holtmann5976e602013-10-06 04:08:14 -07007317static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7318{
7319 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007320}
7321
7322void mgmt_reenable_advertising(struct hci_dev *hdev)
7323{
7324 struct hci_request req;
7325
Marcel Holtmann5976e602013-10-06 04:08:14 -07007326 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7327 return;
7328
7329 hci_req_init(&req, hdev);
7330 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007331 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007332}