blob: 6b3f5537e44133dcdc39f066415b5f4e29b2a967 [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 Holtmannedd3896b2014-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 Hedberg9df74652014-12-19 22:26:03 +0200142 int (*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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200256
Andre Guedes790eff42012-06-07 19:05:46 -0300257 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200273 kfree_skb(skb);
274
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300275 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200276}
277
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Holtmann05b3c3e2014-12-31 14:43:18 -0800573 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300580 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200581 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300582 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200583
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200584 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
585 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586 settings |= MGMT_SETTING_CONFIGURATION;
587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588 return settings;
589}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_current_settings(struct hci_dev *hdev)
592{
593 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200594
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200595 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100596 settings |= MGMT_SETTING_POWERED;
597
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200598 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200599 settings |= MGMT_SETTING_CONNECTABLE;
600
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500601 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
602 settings |= MGMT_SETTING_FAST_CONNECTABLE;
603
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200604 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605 settings |= MGMT_SETTING_DISCOVERABLE;
606
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300607 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300608 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609
Johan Hedberg56f87902013-10-02 13:43:13 +0300610 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_BREDR;
612
Johan Hedberg06199cf2012-02-22 16:37:11 +0200613 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200615
Johan Hedberg47990ea2012-02-22 11:58:37 +0200616 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200618
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200621
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200622 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
623 settings |= MGMT_SETTING_HS;
624
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200625 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300626 settings |= MGMT_SETTING_ADVERTISING;
627
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800628 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
629 settings |= MGMT_SETTING_SECURE_CONN;
630
Johan Hedberg0663b292014-06-24 13:15:50 +0300631 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800632 settings |= MGMT_SETTING_DEBUG_KEYS;
633
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
635 settings |= MGMT_SETTING_PRIVACY;
636
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200637 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200638}
639
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300640#define PNP_INFO_SVCLASS_ID 0x1200
641
Johan Hedberg213202e2013-01-27 00:31:33 +0200642static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
643{
644 u8 *ptr = data, *uuids_start = NULL;
645 struct bt_uuid *uuid;
646
647 if (len < 4)
648 return ptr;
649
650 list_for_each_entry(uuid, &hdev->uuids, list) {
651 u16 uuid16;
652
653 if (uuid->size != 16)
654 continue;
655
656 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
657 if (uuid16 < 0x1100)
658 continue;
659
660 if (uuid16 == PNP_INFO_SVCLASS_ID)
661 continue;
662
663 if (!uuids_start) {
664 uuids_start = ptr;
665 uuids_start[0] = 1;
666 uuids_start[1] = EIR_UUID16_ALL;
667 ptr += 2;
668 }
669
670 /* Stop if not enough space to put next UUID */
671 if ((ptr - data) + sizeof(u16) > len) {
672 uuids_start[1] = EIR_UUID16_SOME;
673 break;
674 }
675
676 *ptr++ = (uuid16 & 0x00ff);
677 *ptr++ = (uuid16 & 0xff00) >> 8;
678 uuids_start[0] += sizeof(uuid16);
679 }
680
681 return ptr;
682}
683
Johan Hedbergcdf19632013-01-27 00:31:34 +0200684static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
685{
686 u8 *ptr = data, *uuids_start = NULL;
687 struct bt_uuid *uuid;
688
689 if (len < 6)
690 return ptr;
691
692 list_for_each_entry(uuid, &hdev->uuids, list) {
693 if (uuid->size != 32)
694 continue;
695
696 if (!uuids_start) {
697 uuids_start = ptr;
698 uuids_start[0] = 1;
699 uuids_start[1] = EIR_UUID32_ALL;
700 ptr += 2;
701 }
702
703 /* Stop if not enough space to put next UUID */
704 if ((ptr - data) + sizeof(u32) > len) {
705 uuids_start[1] = EIR_UUID32_SOME;
706 break;
707 }
708
709 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
710 ptr += sizeof(u32);
711 uuids_start[0] += sizeof(u32);
712 }
713
714 return ptr;
715}
716
Johan Hedbergc00d5752013-01-27 00:31:35 +0200717static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
718{
719 u8 *ptr = data, *uuids_start = NULL;
720 struct bt_uuid *uuid;
721
722 if (len < 18)
723 return ptr;
724
725 list_for_each_entry(uuid, &hdev->uuids, list) {
726 if (uuid->size != 128)
727 continue;
728
729 if (!uuids_start) {
730 uuids_start = ptr;
731 uuids_start[0] = 1;
732 uuids_start[1] = EIR_UUID128_ALL;
733 ptr += 2;
734 }
735
736 /* Stop if not enough space to put next UUID */
737 if ((ptr - data) + 16 > len) {
738 uuids_start[1] = EIR_UUID128_SOME;
739 break;
740 }
741
742 memcpy(ptr, uuid->uuid, 16);
743 ptr += 16;
744 uuids_start[0] += 16;
745 }
746
747 return ptr;
748}
749
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300750static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
751{
752 struct pending_cmd *cmd;
753
754 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
755 if (cmd->opcode == opcode)
756 return cmd;
757 }
758
759 return NULL;
760}
761
Johan Hedberg95868422014-06-28 17:54:07 +0300762static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
763 struct hci_dev *hdev,
764 const void *data)
765{
766 struct pending_cmd *cmd;
767
768 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
769 if (cmd->user_data != data)
770 continue;
771 if (cmd->opcode == opcode)
772 return cmd;
773 }
774
775 return NULL;
776}
777
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700778static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
779{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700780 u8 ad_len = 0;
781 size_t name_len;
782
783 name_len = strlen(hdev->dev_name);
784 if (name_len > 0) {
785 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
786
787 if (name_len > max_len) {
788 name_len = max_len;
789 ptr[1] = EIR_NAME_SHORT;
790 } else
791 ptr[1] = EIR_NAME_COMPLETE;
792
793 ptr[0] = name_len + 1;
794
795 memcpy(ptr + 2, hdev->dev_name, name_len);
796
797 ad_len += (name_len + 2);
798 ptr += (name_len + 2);
799 }
800
801 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802}
803
804static void update_scan_rsp_data(struct hci_request *req)
805{
806 struct hci_dev *hdev = req->hdev;
807 struct hci_cp_le_set_scan_rsp_data cp;
808 u8 len;
809
Johan Hedberg7751ef12013-10-19 23:38:15 +0300810 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811 return;
812
813 memset(&cp, 0, sizeof(cp));
814
815 len = create_scan_rsp_data(hdev, cp.data);
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 if (hdev->scan_rsp_data_len == len &&
818 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819 return;
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
822 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823
824 cp.length = len;
825
826 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
827}
828
Johan Hedberg9a43e252013-10-20 19:00:07 +0300829static u8 get_adv_discov_flags(struct hci_dev *hdev)
830{
831 struct pending_cmd *cmd;
832
833 /* If there's a pending mgmt command the flags will not yet have
834 * their final values, so check for this first.
835 */
836 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
837 if (cmd) {
838 struct mgmt_mode *cp = cmd->param;
839 if (cp->val == 0x01)
840 return LE_AD_GENERAL;
841 else if (cp->val == 0x02)
842 return LE_AD_LIMITED;
843 } else {
844 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_LIMITED;
846 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
847 return LE_AD_GENERAL;
848 }
849
850 return 0;
851}
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854{
855 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberg9a43e252013-10-20 19:00:07 +0300857 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
Johan Hedberge8340042014-01-30 11:16:50 -0800859 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
862 if (flags) {
863 BT_DBG("adv flags 0x%02x", flags);
864
865 ptr[0] = 2;
866 ptr[1] = EIR_FLAGS;
867 ptr[2] = flags;
868
869 ad_len += 3;
870 ptr += 3;
871 }
872
873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
874 ptr[0] = 2;
875 ptr[1] = EIR_TX_POWER;
876 ptr[2] = (u8) hdev->adv_tx_power;
877
878 ad_len += 3;
879 ptr += 3;
880 }
881
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882 return ad_len;
883}
884
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700885static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886{
887 struct hci_dev *hdev = req->hdev;
888 struct hci_cp_le_set_adv_data cp;
889 u8 len;
890
Johan Hedberg10994ce2013-10-19 23:38:16 +0300891 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700892 return;
893
894 memset(&cp, 0, sizeof(cp));
895
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700896 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700897
898 if (hdev->adv_data_len == len &&
899 memcmp(cp.data, hdev->adv_data, len) == 0)
900 return;
901
902 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
903 hdev->adv_data_len = len;
904
905 cp.length = len;
906
907 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
908}
909
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300910int mgmt_update_adv_data(struct hci_dev *hdev)
911{
912 struct hci_request req;
913
914 hci_req_init(&req, hdev);
915 update_adv_data(&req);
916
917 return hci_req_run(&req, NULL);
918}
919
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920static void create_eir(struct hci_dev *hdev, u8 *data)
921{
922 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923 size_t name_len;
924
925 name_len = strlen(hdev->dev_name);
926
927 if (name_len > 0) {
928 /* EIR Data type */
929 if (name_len > 48) {
930 name_len = 48;
931 ptr[1] = EIR_NAME_SHORT;
932 } else
933 ptr[1] = EIR_NAME_COMPLETE;
934
935 /* EIR Data length */
936 ptr[0] = name_len + 1;
937
938 memcpy(ptr + 2, hdev->dev_name, name_len);
939
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300940 ptr += (name_len + 2);
941 }
942
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100943 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr[0] = 2;
945 ptr[1] = EIR_TX_POWER;
946 ptr[2] = (u8) hdev->inq_tx_power;
947
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr += 3;
949 }
950
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700951 if (hdev->devid_source > 0) {
952 ptr[0] = 9;
953 ptr[1] = EIR_DEVICE_ID;
954
955 put_unaligned_le16(hdev->devid_source, ptr + 2);
956 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
957 put_unaligned_le16(hdev->devid_product, ptr + 6);
958 put_unaligned_le16(hdev->devid_version, ptr + 8);
959
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700960 ptr += 10;
961 }
962
Johan Hedberg213202e2013-01-27 00:31:33 +0200963 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200964 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200965 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966}
967
Johan Hedberg890ea892013-03-15 17:06:52 -0500968static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969{
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300971 struct hci_cp_write_eir cp;
972
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200973 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200975
Johan Hedberg976eb202012-10-24 21:12:01 +0300976 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200979 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200982 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
985 memset(&cp, 0, sizeof(cp));
986
987 create_eir(hdev, cp.data);
988
989 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991
992 memcpy(hdev->eir, cp.data, sizeof(cp.data));
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995}
996
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997static u8 get_service_classes(struct hci_dev *hdev)
998{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 val = 0;
1001
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004
1005 return val;
1006}
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009{
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001011 u8 cod[3];
1012
1013 BT_DBG("%s", hdev->name);
1014
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001015 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001017
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001018 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1019 return;
1020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001021 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001022 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
1024 cod[0] = hdev->minor_class;
1025 cod[1] = hdev->major_class;
1026 cod[2] = get_service_classes(hdev);
1027
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001028 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1029 cod[1] |= 0x20;
1030
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035}
1036
Johan Hedberga4858cb2014-02-25 19:56:31 +02001037static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038{
1039 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040
1041 /* If there's a pending mgmt command the flag will not yet have
1042 * it's final value, so check for this first.
1043 */
1044 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1045 if (cmd) {
1046 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048 }
1049
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051}
1052
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001053static void disable_advertising(struct hci_request *req)
1054{
1055 u8 enable = 0x00;
1056
1057 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1058}
1059
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001060static void enable_advertising(struct hci_request *req)
1061{
1062 struct hci_dev *hdev = req->hdev;
1063 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001064 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001066
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001067 if (hci_conn_num(hdev, LE_LINK) > 0)
1068 return;
1069
1070 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1071 disable_advertising(req);
1072
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001073 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001074 * hci_update_random_address knows that it's safe to go ahead
1075 * and write a new random address. The flag will be set back on
1076 * as soon as the SET_ADV_ENABLE HCI command completes.
1077 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001078 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001081
Johan Hedberga4858cb2014-02-25 19:56:31 +02001082 /* Set require_privacy to true only when non-connectable
1083 * advertising is used. In that case it is fine to use a
1084 * non-resolvable private address.
1085 */
1086 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001087 return;
1088
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001089 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001090 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1091 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001092 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001093 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001094 cp.channel_map = hdev->le_adv_channel_map;
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1097
1098 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1099}
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101static void service_cache_off(struct work_struct *work)
1102{
1103 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001104 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001107 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 return;
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 hci_req_init(&req, hdev);
1111
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 hci_dev_lock(hdev);
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 update_eir(&req);
1115 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116
1117 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001118
1119 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120}
1121
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122static void rpa_expired(struct work_struct *work)
1123{
1124 struct hci_dev *hdev = container_of(work, struct hci_dev,
1125 rpa_expired.work);
1126 struct hci_request req;
1127
1128 BT_DBG("");
1129
1130 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1131
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001132 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001133 return;
1134
1135 /* The generation of a new RPA and programming it into the
1136 * controller happens in the enable_advertising() function.
1137 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 hci_req_run(&req, NULL);
1141}
1142
Johan Hedberg6a919082012-02-28 06:17:26 +02001143static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001144{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001146 return;
1147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001149 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 /* Non-mgmt controlled devices get this bit set
1152 * implicitly so that pairing works for them, however
1153 * for mgmt we require user-space to explicitly enable
1154 * it
1155 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001156 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001157}
1158
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001159static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001161{
1162 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 memset(&rp, 0, sizeof(rp));
1169
Johan Hedberg03811012010-12-08 00:21:06 +02001170 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001173 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1176 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1177
1178 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
1180 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001181 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001183 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001184
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001185 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001187}
1188
1189static void mgmt_pending_free(struct pending_cmd *cmd)
1190{
1191 sock_put(cmd->sk);
1192 kfree(cmd->param);
1193 kfree(cmd);
1194}
1195
1196static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 struct hci_dev *hdev, void *data,
1198 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001199{
1200 struct pending_cmd *cmd;
1201
Johan Hedbergfca20012014-06-28 17:54:05 +03001202 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 if (!cmd)
1204 return NULL;
1205
1206 cmd->opcode = opcode;
1207 cmd->index = hdev->id;
1208
Johan Hedberg323b0b82014-12-05 13:36:01 +02001209 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001210 if (!cmd->param) {
1211 kfree(cmd);
1212 return NULL;
1213 }
1214
Johan Hedberg323b0b82014-12-05 13:36:01 +02001215 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b212012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedberg9df74652014-12-19 22:26:03 +02001489static int generic_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001490{
Johan Hedberg9df74652014-12-19 22:26:03 +02001491 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1492 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001493}
1494
Johan Hedberg9df74652014-12-19 22:26:03 +02001495static int addr_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001496{
Johan Hedberg9df74652014-12-19 22:26:03 +02001497 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001569 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001816 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001850 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302202 hci_dev_lock(hdev);
2203
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002204 if (status) {
2205 u8 mgmt_err = mgmt_status(status);
2206
2207 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2208 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302209 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002210 }
2211
2212 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2213
2214 new_settings(hdev, match.sk);
2215
2216 if (match.sk)
2217 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002218
2219 /* Make sure the controller has a good default for
2220 * advertising data. Restrict the update to when LE
2221 * has actually been enabled. During power on, the
2222 * update in powered_update_hci will take care of it.
2223 */
2224 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2225 struct hci_request req;
2226
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002230 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002231 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002232 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302233
2234unlock:
2235 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236}
2237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239{
2240 struct mgmt_mode *cp = data;
2241 struct hci_cp_write_le_host_supported hci_cp;
2242 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002245 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_le_capable(hdev))
2250 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_INVALID_PARAMS);
2256
Johan Hedbergc73eee92013-04-19 18:35:21 +03002257 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2260 MGMT_STATUS_REJECTED);
2261
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002262 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263
2264 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002265 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002267 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 bool changed = false;
2269
2270 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2271 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2272 changed = true;
2273 }
2274
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002275 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2276 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002277 changed = true;
2278 }
2279
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2281 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283
2284 if (changed)
2285 err = new_settings(hdev, sk);
2286
Johan Hedberg1de028c2012-02-29 19:55:35 -08002287 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288 }
2289
Johan Hedberg4375f102013-09-25 13:26:10 +03002290 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2291 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002300 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002303 hci_req_init(&req, hdev);
2304
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 memset(&hci_cp, 0, sizeof(hci_cp));
2306
2307 if (val) {
2308 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002309 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002310 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 }
2314
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002315 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2316 &hci_cp);
2317
2318 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302319 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322unlock:
2323 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 return err;
2325}
2326
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002327/* This is a helper function to test for pending mgmt commands that can
2328 * cause CoD or EIR HCI commands. We can only allow one such pending
2329 * mgmt command at a time since otherwise we cannot easily track what
2330 * the current values are, will be, and based on that calculate if a new
2331 * HCI command needs to be sent and if yes with what value.
2332 */
2333static bool pending_eir_or_class(struct hci_dev *hdev)
2334{
2335 struct pending_cmd *cmd;
2336
2337 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2338 switch (cmd->opcode) {
2339 case MGMT_OP_ADD_UUID:
2340 case MGMT_OP_REMOVE_UUID:
2341 case MGMT_OP_SET_DEV_CLASS:
2342 case MGMT_OP_SET_POWERED:
2343 return true;
2344 }
2345 }
2346
2347 return false;
2348}
2349
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002350static const u8 bluetooth_base_uuid[] = {
2351 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2352 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2353};
2354
2355static u8 get_uuid_size(const u8 *uuid)
2356{
2357 u32 val;
2358
2359 if (memcmp(uuid, bluetooth_base_uuid, 12))
2360 return 128;
2361
2362 val = get_unaligned_le32(&uuid[12]);
2363 if (val > 0xffff)
2364 return 32;
2365
2366 return 16;
2367}
2368
Johan Hedberg92da6092013-03-15 17:06:55 -05002369static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2370{
2371 struct pending_cmd *cmd;
2372
2373 hci_dev_lock(hdev);
2374
2375 cmd = mgmt_pending_find(mgmt_op, hdev);
2376 if (!cmd)
2377 goto unlock;
2378
2379 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2380 hdev->dev_class, 3);
2381
2382 mgmt_pending_remove(cmd);
2383
2384unlock:
2385 hci_dev_unlock(hdev);
2386}
2387
2388static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002397 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002398 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto failed;
2411 }
2412
Andre Guedes92c4c202012-06-07 19:05:44 -03002413 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002414 if (!uuid) {
2415 err = -ENOMEM;
2416 goto failed;
2417 }
2418
2419 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002421 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedbergde66aa62013-01-27 00:31:27 +02002423 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedberg890ea892013-03-15 17:06:52 -05002425 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 update_class(&req);
2428 update_eir(&req);
2429
Johan Hedberg92da6092013-03-15 17:06:55 -05002430 err = hci_req_run(&req, add_uuid_complete);
2431 if (err < 0) {
2432 if (err != -ENODATA)
2433 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002436 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002437 goto failed;
2438 }
2439
2440 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002442 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 goto failed;
2444 }
2445
2446 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447
2448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002449 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 return err;
2451}
2452
Johan Hedberg24b78d02012-02-23 23:24:30 +02002453static bool enable_service_cache(struct hci_dev *hdev)
2454{
2455 if (!hdev_is_powered(hdev))
2456 return false;
2457
2458 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002459 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2460 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002461 return true;
2462 }
2463
2464 return false;
2465}
2466
Johan Hedberg92da6092013-03-15 17:06:55 -05002467static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2468{
2469 BT_DBG("status 0x%02x", status);
2470
2471 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2472}
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002477 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 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 -05002481 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 int err, found;
2483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002484 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002488 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002491 goto unlock;
2492 }
2493
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002494 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002495 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg24b78d02012-02-23 23:24:30 +02002497 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002500 goto unlock;
2501 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002502
Johan Hedberg9246a862012-02-23 21:33:16 +02002503 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504 }
2505
2506 found = 0;
2507
Johan Hedberg056341c2013-01-27 00:31:30 +02002508 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2510 continue;
2511
2512 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002513 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 found++;
2515 }
2516
2517 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002519 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 goto unlock;
2521 }
2522
Johan Hedberg9246a862012-02-23 21:33:16 +02002523update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527 update_eir(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, remove_uuid_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 return err;
2550}
2551
Johan Hedberg92da6092013-03-15 17:06:55 -05002552static void set_class_complete(struct hci_dev *hdev, u8 status)
2553{
2554 BT_DBG("status 0x%02x", status);
2555
2556 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002561{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002562 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002563 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002564 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565 int err;
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002569 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_NOT_SUPPORTED);
2572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002574
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002575 if (pending_eir_or_class(hdev)) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_BUSY);
2578 goto unlock;
2579 }
2580
2581 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2582 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2583 MGMT_STATUS_INVALID_PARAMS);
2584 goto unlock;
2585 }
2586
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002587 hdev->major_class = cp->major;
2588 hdev->minor_class = cp->minor;
2589
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002590 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002593 goto unlock;
2594 }
2595
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 hci_req_init(&req, hdev);
2597
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002598 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002599 hci_dev_unlock(hdev);
2600 cancel_delayed_work_sync(&hdev->service_cache);
2601 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002602 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606
Johan Hedberg92da6092013-03-15 17:06:55 -05002607 err = hci_req_run(&req, set_class_complete);
2608 if (err < 0) {
2609 if (err != -ENODATA)
2610 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002613 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 goto unlock;
2615 }
2616
2617 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002618 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002619 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 goto unlock;
2621 }
2622
2623 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624
Johan Hedbergb5235a62012-02-21 14:32:24 +02002625unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627 return err;
2628}
2629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002631 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002633 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002634 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2635 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002637 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002638 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002640 BT_DBG("request for %s", hdev->name);
2641
2642 if (!lmp_bredr_capable(hdev))
2643 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2644 MGMT_STATUS_NOT_SUPPORTED);
2645
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002646 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002647 if (key_count > max_key_count) {
2648 BT_ERR("load_link_keys: too big key_count value %u",
2649 key_count);
2650 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2651 MGMT_STATUS_INVALID_PARAMS);
2652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberg86742e12011-11-07 23:13:38 +02002654 expected_len = sizeof(*cp) + key_count *
2655 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002656 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002657 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002658 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedberg4ae143012013-01-20 14:27:13 +02002663 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2664 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2665 MGMT_STATUS_INVALID_PARAMS);
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002668 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 for (i = 0; i < key_count; i++) {
2671 struct mgmt_link_key_info *key = &cp->keys[i];
2672
Marcel Holtmann8e991132014-01-10 02:07:25 -08002673 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_INVALID_PARAMS);
2676 }
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
2680 hci_link_keys_clear(hdev);
2681
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2684 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2687 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002688
2689 if (changed)
2690 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002692 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002693 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg58e92932014-06-24 14:00:26 +03002695 /* Always ignore debug keys and require a new pairing if
2696 * the user wants to use them.
2697 */
2698 if (key->type == HCI_LK_DEBUG_COMBINATION)
2699 continue;
2700
Johan Hedberg7652ff62014-06-24 13:15:49 +03002701 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2702 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 }
2704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002709 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710}
2711
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714{
2715 struct mgmt_ev_device_unpaired ev;
2716
2717 bacpy(&ev.addr.bdaddr, bdaddr);
2718 ev.addr.type = addr_type;
2719
2720 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002722}
2723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 struct mgmt_cp_unpair_device *cp = data;
2728 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 struct hci_cp_disconnect dc;
2730 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 int err;
2733
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
2739 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
2742
Johan Hedberg118da702013-01-20 14:27:20 +02002743 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2744 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2745 MGMT_STATUS_INVALID_PARAMS,
2746 &rp, sizeof(rp));
2747
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002748 hci_dev_lock(hdev);
2749
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002750 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002751 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 goto unlock;
2754 }
2755
Johan Hedberge0b2b272014-02-18 17:14:31 +02002756 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002757 /* If disconnection is requested, then look up the
2758 * connection. If the remote device is connected, it
2759 * will be later used to terminate the link.
2760 *
2761 * Setting it to NULL explicitly will cause no
2762 * termination of the link.
2763 */
2764 if (cp->disconnect)
2765 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2766 &cp->addr.bdaddr);
2767 else
2768 conn = NULL;
2769
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 } else {
2772 u8 addr_type;
2773
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002774 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2775 &cp->addr.bdaddr);
2776 if (conn) {
2777 /* Defer clearing up the connection parameters
2778 * until closing to give a chance of keeping
2779 * them if a repairing happens.
2780 */
2781 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2782
2783 /* If disconnection is not requested, then
2784 * clear the connection variable so that the
2785 * link is not terminated.
2786 */
2787 if (!cp->disconnect)
2788 conn = NULL;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_LE_PUBLIC)
2792 addr_type = ADDR_LE_DEV_PUBLIC;
2793 else
2794 addr_type = ADDR_LE_DEV_RANDOM;
2795
Johan Hedberga7ec7332014-02-18 17:14:35 +02002796 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2797
Johan Hedberge0b2b272014-02-18 17:14:31 +02002798 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2799 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002802 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002803 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 goto unlock;
2805 }
2806
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002807 /* If the connection variable is set, then termination of the
2808 * link is requested.
2809 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002810 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002813 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 }
2816
Johan Hedberg124f6e32012-02-09 13:50:12 +02002817 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 if (!cmd) {
2820 err = -ENOMEM;
2821 goto unlock;
2822 }
2823
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002824 cmd->cmd_complete = addr_cmd_complete;
2825
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002826 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002827 dc.reason = 0x13; /* Remote User Terminated Connection */
2828 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2829 if (err < 0)
2830 mgmt_pending_remove(cmd);
2831
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002833 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002834 return err;
2835}
2836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002837static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002839{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002840 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002841 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002842 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002843 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844 int err;
2845
2846 BT_DBG("");
2847
Johan Hedberg06a63b12013-01-20 14:27:21 +02002848 memset(&rp, 0, sizeof(rp));
2849 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2850 rp.addr.type = cp->addr.type;
2851
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002852 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002853 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2854 MGMT_STATUS_INVALID_PARAMS,
2855 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002856
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002857 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002858
2859 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002860 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2861 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002862 goto failed;
2863 }
2864
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002865 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002866 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2867 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002868 goto failed;
2869 }
2870
Andre Guedes591f47f2012-04-24 21:02:49 -03002871 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002872 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2873 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002874 else
2875 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002876
Vishal Agarwalf9607272012-06-13 05:32:43 +05302877 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002878 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2879 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 goto failed;
2881 }
2882
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002883 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002884 if (!cmd) {
2885 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002887 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002888
Johan Hedbergf5818c22014-12-05 13:36:02 +02002889 cmd->cmd_complete = generic_cmd_complete;
2890
Johan Hedberge3f2f922014-08-18 20:33:33 +03002891 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002893 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894
2895failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002897 return err;
2898}
2899
Andre Guedes57c14772012-04-24 21:02:50 -03002900static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002901{
2902 switch (link_type) {
2903 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002904 switch (addr_type) {
2905 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002906 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002907
Johan Hedberg48264f02011-11-09 13:58:58 +02002908 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002909 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002910 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002911 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002912
Johan Hedberg4c659c32011-11-07 23:13:39 +02002913 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002914 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002915 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002916 }
2917}
2918
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002919static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2920 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002921{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002922 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002923 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002924 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002925 int err;
2926 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002927
2928 BT_DBG("");
2929
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002930 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002931
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002935 goto unlock;
2936 }
2937
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002938 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002939 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2940 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002941 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002942 }
2943
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002944 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002945 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002946 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002947 err = -ENOMEM;
2948 goto unlock;
2949 }
2950
Johan Hedberg2784eb42011-01-21 13:56:35 +02002951 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002952 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002953 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2954 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002955 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002956 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002957 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002958 continue;
2959 i++;
2960 }
2961
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002962 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002963
Johan Hedberg4c659c32011-11-07 23:13:39 +02002964 /* Recalculate length in case of filtered SCO connections, etc */
2965 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002969
Johan Hedberga38528f2011-01-22 06:46:43 +02002970 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002971
2972unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002973 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002974 return err;
2975}
2976
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002979{
2980 struct pending_cmd *cmd;
2981 int err;
2982
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002983 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002985 if (!cmd)
2986 return -ENOMEM;
2987
Johan Hedbergd8457692012-02-17 14:24:57 +02002988 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002990 if (err < 0)
2991 mgmt_pending_remove(cmd);
2992
2993 return err;
2994}
2995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002996static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002998{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002999 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003000 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003001 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003002 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003003 int err;
3004
3005 BT_DBG("");
3006
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003007 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003008
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003009 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003010 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003011 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012 goto failed;
3013 }
3014
Johan Hedbergd8457692012-02-17 14:24:57 +02003015 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003016 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003017 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003018 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003019 goto failed;
3020 }
3021
3022 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003023 struct mgmt_cp_pin_code_neg_reply ncp;
3024
3025 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003026
3027 BT_ERR("PIN code is not 16 bytes long");
3028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003033
3034 goto failed;
3035 }
3036
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003037 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003038 if (!cmd) {
3039 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003041 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003043 cmd->cmd_complete = addr_cmd_complete;
3044
Johan Hedbergd8457692012-02-17 14:24:57 +02003045 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003047 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003048
3049 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3050 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003051 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003052
3053failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003054 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003055 return err;
3056}
3057
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003058static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3059 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003061 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003062
3063 BT_DBG("");
3064
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003065 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3066 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3067 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3068
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003069 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003070
3071 hdev->io_capability = cp->io_capability;
3072
3073 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003074 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003076 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003077
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003078 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3079 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003080}
3081
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003082static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003083{
3084 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003085 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003087 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003088 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3089 continue;
3090
Johan Hedberge9a416b2011-02-19 12:05:56 -03003091 if (cmd->user_data != conn)
3092 continue;
3093
3094 return cmd;
3095 }
3096
3097 return NULL;
3098}
3099
Johan Hedberg9df74652014-12-19 22:26:03 +02003100static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003101{
3102 struct mgmt_rp_pair_device rp;
3103 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003104 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105
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 Hedberg9df74652014-12-19 22:26:03 +02003109 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3110 &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 Hedberg9df74652014-12-19 22:26:03 +02003125
3126 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003127}
3128
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003129void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3130{
3131 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3132 struct pending_cmd *cmd;
3133
3134 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003135 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003136 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003137 mgmt_pending_remove(cmd);
3138 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003139}
3140
Johan Hedberge9a416b2011-02-19 12:05:56 -03003141static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3142{
3143 struct pending_cmd *cmd;
3144
3145 BT_DBG("status %u", status);
3146
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003147 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003148 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003149 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003150 return;
3151 }
3152
3153 cmd->cmd_complete(cmd, mgmt_status(status));
3154 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003155}
3156
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003157static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303158{
3159 struct pending_cmd *cmd;
3160
3161 BT_DBG("status %u", status);
3162
3163 if (!status)
3164 return;
3165
3166 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003167 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303168 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003169 return;
3170 }
3171
3172 cmd->cmd_complete(cmd, mgmt_status(status));
3173 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303174}
3175
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003176static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003177 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003178{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003179 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003180 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003181 struct pending_cmd *cmd;
3182 u8 sec_level, auth_type;
3183 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003184 int err;
3185
3186 BT_DBG("");
3187
Szymon Jancf950a30e2013-01-18 12:48:07 +01003188 memset(&rp, 0, sizeof(rp));
3189 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3190 rp.addr.type = cp->addr.type;
3191
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003192 if (!bdaddr_type_is_valid(cp->addr.type))
3193 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3194 MGMT_STATUS_INVALID_PARAMS,
3195 &rp, sizeof(rp));
3196
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003197 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3198 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3199 MGMT_STATUS_INVALID_PARAMS,
3200 &rp, sizeof(rp));
3201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003202 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003203
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003204 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003205 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3206 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003207 goto unlock;
3208 }
3209
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003210 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003211 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003212
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003213 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003214 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3215 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003216 } else {
3217 u8 addr_type;
3218
3219 /* Convert from L2CAP channel address type to HCI address type
3220 */
3221 if (cp->addr.type == BDADDR_LE_PUBLIC)
3222 addr_type = ADDR_LE_DEV_PUBLIC;
3223 else
3224 addr_type = ADDR_LE_DEV_RANDOM;
3225
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003226 /* When pairing a new device, it is expected to remember
3227 * this device for future connections. Adding the connection
3228 * parameter information ahead of time allows tracking
3229 * of the slave preferred values and will speed up any
3230 * further connection establishment.
3231 *
3232 * If connection parameters already exist, then they
3233 * will be kept and this function does nothing.
3234 */
3235 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3236
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003237 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003238 sec_level, HCI_LE_CONN_TIMEOUT,
3239 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003240 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003241
Ville Tervo30e76272011-02-22 16:10:53 -03003242 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003243 int status;
3244
3245 if (PTR_ERR(conn) == -EBUSY)
3246 status = MGMT_STATUS_BUSY;
3247 else
3248 status = MGMT_STATUS_CONNECT_FAILED;
3249
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003250 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003251 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003252 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003253 goto unlock;
3254 }
3255
3256 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003257 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003258 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003259 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003260 goto unlock;
3261 }
3262
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003263 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003264 if (!cmd) {
3265 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003266 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003267 goto unlock;
3268 }
3269
Johan Hedberg04ab2742014-12-05 13:36:04 +02003270 cmd->cmd_complete = pairing_complete;
3271
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003272 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003273 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003274 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003275 conn->security_cfm_cb = pairing_complete_cb;
3276 conn->disconn_cfm_cb = pairing_complete_cb;
3277 } else {
3278 conn->connect_cfm_cb = le_pairing_complete_cb;
3279 conn->security_cfm_cb = le_pairing_complete_cb;
3280 conn->disconn_cfm_cb = le_pairing_complete_cb;
3281 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003282
Johan Hedberge9a416b2011-02-19 12:05:56 -03003283 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003284 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003286 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003287 hci_conn_security(conn, sec_level, auth_type, true)) {
3288 cmd->cmd_complete(cmd, 0);
3289 mgmt_pending_remove(cmd);
3290 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003291
3292 err = 0;
3293
3294unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003295 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003296 return err;
3297}
3298
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003299static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3300 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003301{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003302 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003303 struct pending_cmd *cmd;
3304 struct hci_conn *conn;
3305 int err;
3306
3307 BT_DBG("");
3308
Johan Hedberg28424702012-02-02 04:02:29 +02003309 hci_dev_lock(hdev);
3310
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003311 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003312 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003313 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003314 goto unlock;
3315 }
3316
Johan Hedberg28424702012-02-02 04:02:29 +02003317 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3318 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003319 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003320 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003321 goto unlock;
3322 }
3323
3324 conn = cmd->user_data;
3325
3326 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003327 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003328 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003329 goto unlock;
3330 }
3331
Johan Hedberga511b352014-12-11 21:45:45 +02003332 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3333 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003334
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003335 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003336 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003337unlock:
3338 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003339 return err;
3340}
3341
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003342static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003343 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003344 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003345{
Johan Hedberga5c29682011-02-19 12:05:57 -03003346 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003347 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003348 int err;
3349
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003350 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003351
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003352 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003353 err = cmd_complete(sk, hdev->id, mgmt_op,
3354 MGMT_STATUS_NOT_POWERED, addr,
3355 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003356 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003357 }
3358
Johan Hedberg1707c602013-03-15 17:07:15 -05003359 if (addr->type == BDADDR_BREDR)
3360 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003361 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003362 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003363
Johan Hedberg272d90d2012-02-09 15:26:12 +02003364 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003365 err = cmd_complete(sk, hdev->id, mgmt_op,
3366 MGMT_STATUS_NOT_CONNECTED, addr,
3367 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003368 goto done;
3369 }
3370
Johan Hedberg1707c602013-03-15 17:07:15 -05003371 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003372 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003373 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003374 err = cmd_complete(sk, hdev->id, mgmt_op,
3375 MGMT_STATUS_SUCCESS, addr,
3376 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003377 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003378 err = cmd_complete(sk, hdev->id, mgmt_op,
3379 MGMT_STATUS_FAILED, addr,
3380 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003381
Brian Gix47c15e22011-11-16 13:53:14 -08003382 goto done;
3383 }
3384
Johan Hedberg1707c602013-03-15 17:07:15 -05003385 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003386 if (!cmd) {
3387 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003388 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003389 }
3390
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003391 cmd->cmd_complete = addr_cmd_complete;
3392
Brian Gix0df4c182011-11-16 13:53:13 -08003393 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003394 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3395 struct hci_cp_user_passkey_reply cp;
3396
Johan Hedberg1707c602013-03-15 17:07:15 -05003397 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003398 cp.passkey = passkey;
3399 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3400 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003401 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3402 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003403
Johan Hedberga664b5b2011-02-19 12:06:02 -03003404 if (err < 0)
3405 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003406
Brian Gix0df4c182011-11-16 13:53:13 -08003407done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003408 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003409 return err;
3410}
3411
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303412static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3413 void *data, u16 len)
3414{
3415 struct mgmt_cp_pin_code_neg_reply *cp = data;
3416
3417 BT_DBG("");
3418
Johan Hedberg1707c602013-03-15 17:07:15 -05003419 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303420 MGMT_OP_PIN_CODE_NEG_REPLY,
3421 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3422}
3423
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003424static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3425 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003426{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003427 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003428
3429 BT_DBG("");
3430
3431 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003432 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003433 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003436 MGMT_OP_USER_CONFIRM_REPLY,
3437 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003438}
3439
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003440static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003441 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003442{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003443 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003444
3445 BT_DBG("");
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3449 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003450}
3451
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003452static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3453 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003454{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003455 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003456
3457 BT_DBG("");
3458
Johan Hedberg1707c602013-03-15 17:07:15 -05003459 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003460 MGMT_OP_USER_PASSKEY_REPLY,
3461 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003462}
3463
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003464static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003465 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003466{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003467 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003468
3469 BT_DBG("");
3470
Johan Hedberg1707c602013-03-15 17:07:15 -05003471 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003472 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3473 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003474}
3475
Johan Hedberg13928972013-03-15 17:07:00 -05003476static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003477{
Johan Hedberg13928972013-03-15 17:07:00 -05003478 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003479 struct hci_cp_write_local_name cp;
3480
Johan Hedberg13928972013-03-15 17:07:00 -05003481 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003482
Johan Hedberg890ea892013-03-15 17:06:52 -05003483 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003484}
3485
Johan Hedberg13928972013-03-15 17:07:00 -05003486static void set_name_complete(struct hci_dev *hdev, u8 status)
3487{
3488 struct mgmt_cp_set_local_name *cp;
3489 struct pending_cmd *cmd;
3490
3491 BT_DBG("status 0x%02x", status);
3492
3493 hci_dev_lock(hdev);
3494
3495 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3496 if (!cmd)
3497 goto unlock;
3498
3499 cp = cmd->param;
3500
3501 if (status)
3502 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3503 mgmt_status(status));
3504 else
3505 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3506 cp, sizeof(*cp));
3507
3508 mgmt_pending_remove(cmd);
3509
3510unlock:
3511 hci_dev_unlock(hdev);
3512}
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003516{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003517 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003518 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003519 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003520 int err;
3521
3522 BT_DBG("");
3523
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003524 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003525
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003526 /* If the old values are the same as the new ones just return a
3527 * direct command complete event.
3528 */
3529 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3530 !memcmp(hdev->short_name, cp->short_name,
3531 sizeof(hdev->short_name))) {
3532 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3533 data, len);
3534 goto failed;
3535 }
3536
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003537 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003538
Johan Hedbergb5235a62012-02-21 14:32:24 +02003539 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003540 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003541
3542 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003543 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003544 if (err < 0)
3545 goto failed;
3546
3547 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003548 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003549
Johan Hedbergb5235a62012-02-21 14:32:24 +02003550 goto failed;
3551 }
3552
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003553 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003554 if (!cmd) {
3555 err = -ENOMEM;
3556 goto failed;
3557 }
3558
Johan Hedberg13928972013-03-15 17:07:00 -05003559 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3560
Johan Hedberg890ea892013-03-15 17:06:52 -05003561 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003562
3563 if (lmp_bredr_capable(hdev)) {
3564 update_name(&req);
3565 update_eir(&req);
3566 }
3567
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003568 /* The name is stored in the scan response data and so
3569 * no need to udpate the advertising data here.
3570 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003571 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003572 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003573
Johan Hedberg13928972013-03-15 17:07:00 -05003574 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003575 if (err < 0)
3576 mgmt_pending_remove(cmd);
3577
3578failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003579 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003580 return err;
3581}
3582
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003583static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003584 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003585{
Szymon Jancc35938b2011-03-22 13:12:21 +01003586 struct pending_cmd *cmd;
3587 int err;
3588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003589 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003590
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003591 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003592
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003593 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003594 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003595 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003596 goto unlock;
3597 }
3598
Andre Guedes9a1a1992012-07-24 15:03:48 -03003599 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003600 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003601 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003602 goto unlock;
3603 }
3604
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003605 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003606 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003607 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003608 goto unlock;
3609 }
3610
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003611 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003612 if (!cmd) {
3613 err = -ENOMEM;
3614 goto unlock;
3615 }
3616
Johan Hedberg710f11c2014-05-26 11:21:22 +03003617 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003618 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3619 0, NULL);
3620 else
3621 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3622
Szymon Jancc35938b2011-03-22 13:12:21 +01003623 if (err < 0)
3624 mgmt_pending_remove(cmd);
3625
3626unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003627 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003628 return err;
3629}
3630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003631static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003632 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003633{
Szymon Janc2763eda2011-03-22 13:12:22 +01003634 int err;
3635
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003636 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003637
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003638 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003639
Marcel Holtmannec109112014-01-10 02:07:30 -08003640 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3641 struct mgmt_cp_add_remote_oob_data *cp = data;
3642 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003643
Johan Hedbergc19a4952014-11-17 20:52:19 +02003644 if (cp->addr.type != BDADDR_BREDR) {
3645 err = cmd_complete(sk, hdev->id,
3646 MGMT_OP_ADD_REMOTE_OOB_DATA,
3647 MGMT_STATUS_INVALID_PARAMS,
3648 &cp->addr, sizeof(cp->addr));
3649 goto unlock;
3650 }
3651
Marcel Holtmannec109112014-01-10 02:07:30 -08003652 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003653 cp->addr.type, cp->hash,
3654 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003655 if (err < 0)
3656 status = MGMT_STATUS_FAILED;
3657 else
3658 status = MGMT_STATUS_SUCCESS;
3659
3660 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3661 status, &cp->addr, sizeof(cp->addr));
3662 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3663 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003664 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003665 u8 status;
3666
Johan Hedbergc19a4952014-11-17 20:52:19 +02003667 if (cp->addr.type != BDADDR_BREDR) {
3668 err = cmd_complete(sk, hdev->id,
3669 MGMT_OP_ADD_REMOTE_OOB_DATA,
3670 MGMT_STATUS_INVALID_PARAMS,
3671 &cp->addr, sizeof(cp->addr));
3672 goto unlock;
3673 }
3674
Johan Hedberg86df9202014-10-26 20:52:27 +01003675 if (bdaddr_type_is_le(cp->addr.type)) {
3676 rand192 = NULL;
3677 hash192 = NULL;
3678 } else {
3679 rand192 = cp->rand192;
3680 hash192 = cp->hash192;
3681 }
3682
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003683 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003684 cp->addr.type, hash192, rand192,
3685 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003686 if (err < 0)
3687 status = MGMT_STATUS_FAILED;
3688 else
3689 status = MGMT_STATUS_SUCCESS;
3690
3691 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3692 status, &cp->addr, sizeof(cp->addr));
3693 } else {
3694 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3695 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3696 MGMT_STATUS_INVALID_PARAMS);
3697 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003698
Johan Hedbergc19a4952014-11-17 20:52:19 +02003699unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003700 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003701 return err;
3702}
3703
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003704static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003705 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003706{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003707 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003708 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003709 int err;
3710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003711 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003712
Johan Hedbergc19a4952014-11-17 20:52:19 +02003713 if (cp->addr.type != BDADDR_BREDR)
3714 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3715 MGMT_STATUS_INVALID_PARAMS,
3716 &cp->addr, sizeof(cp->addr));
3717
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003718 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003719
Johan Hedbergeedbd582014-11-15 09:34:23 +02003720 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3721 hci_remote_oob_data_clear(hdev);
3722 status = MGMT_STATUS_SUCCESS;
3723 goto done;
3724 }
3725
Johan Hedberg6928a922014-10-26 20:46:09 +01003726 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003727 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003728 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003729 else
Szymon Janca6785be2012-12-13 15:11:21 +01003730 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003731
Johan Hedbergeedbd582014-11-15 09:34:23 +02003732done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003733 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003734 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003735
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003736 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003737 return err;
3738}
3739
Marcel Holtmann80190442014-12-04 11:36:36 +01003740static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003741{
Marcel Holtmann80190442014-12-04 11:36:36 +01003742 struct hci_dev *hdev = req->hdev;
3743 struct hci_cp_le_set_scan_param param_cp;
3744 struct hci_cp_le_set_scan_enable enable_cp;
3745 struct hci_cp_inquiry inq_cp;
3746 /* General inquiry access code (GIAC) */
3747 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3748 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003749 int err;
3750
Marcel Holtmann80190442014-12-04 11:36:36 +01003751 switch (hdev->discovery.type) {
3752 case DISCOV_TYPE_BREDR:
3753 *status = mgmt_bredr_support(hdev);
3754 if (*status)
3755 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003756
Marcel Holtmann80190442014-12-04 11:36:36 +01003757 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3758 *status = MGMT_STATUS_BUSY;
3759 return false;
3760 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003761
Marcel Holtmann80190442014-12-04 11:36:36 +01003762 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003763
Marcel Holtmann80190442014-12-04 11:36:36 +01003764 memset(&inq_cp, 0, sizeof(inq_cp));
3765 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3766 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3767 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3768 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003769
Marcel Holtmann80190442014-12-04 11:36:36 +01003770 case DISCOV_TYPE_LE:
3771 case DISCOV_TYPE_INTERLEAVED:
3772 *status = mgmt_le_support(hdev);
3773 if (*status)
3774 return false;
3775
3776 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3777 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3778 *status = MGMT_STATUS_NOT_SUPPORTED;
3779 return false;
3780 }
3781
3782 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3783 /* Don't let discovery abort an outgoing
3784 * connection attempt that's using directed
3785 * advertising.
3786 */
3787 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3788 BT_CONNECT)) {
3789 *status = MGMT_STATUS_REJECTED;
3790 return false;
3791 }
3792
3793 disable_advertising(req);
3794 }
3795
3796 /* If controller is scanning, it means the background scanning
3797 * is running. Thus, we should temporarily stop it in order to
3798 * set the discovery scanning parameters.
3799 */
3800 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3801 hci_req_add_le_scan_disable(req);
3802
3803 memset(&param_cp, 0, sizeof(param_cp));
3804
3805 /* All active scans will be done with either a resolvable
3806 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003807 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003808 */
3809 err = hci_update_random_address(req, true, &own_addr_type);
3810 if (err < 0) {
3811 *status = MGMT_STATUS_FAILED;
3812 return false;
3813 }
3814
3815 param_cp.type = LE_SCAN_ACTIVE;
3816 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3817 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3818 param_cp.own_address_type = own_addr_type;
3819 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3820 &param_cp);
3821
3822 memset(&enable_cp, 0, sizeof(enable_cp));
3823 enable_cp.enable = LE_SCAN_ENABLE;
3824 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3825 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3826 &enable_cp);
3827 break;
3828
3829 default:
3830 *status = MGMT_STATUS_INVALID_PARAMS;
3831 return false;
3832 }
3833
3834 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003835}
3836
Andre Guedes7c307722013-04-30 15:29:28 -03003837static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3838{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003839 struct pending_cmd *cmd;
3840 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003841
Andre Guedes7c307722013-04-30 15:29:28 -03003842 BT_DBG("status %d", status);
3843
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003844 hci_dev_lock(hdev);
3845
3846 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003847 if (!cmd)
3848 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3849
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003850 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003851 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003852 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003853 }
3854
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003855 if (status) {
3856 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3857 goto unlock;
3858 }
3859
Andre Guedes7c307722013-04-30 15:29:28 -03003860 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003861
3862 switch (hdev->discovery.type) {
3863 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003864 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003865 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003866 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003867 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003868 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003869 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003870 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003871 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003872 default:
3873 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003874 timeout = 0;
3875 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003876 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003877
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003878 if (timeout)
3879 queue_delayed_work(hdev->workqueue,
3880 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003881
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003882unlock:
3883 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003884}
3885
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003886static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003887 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003888{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003889 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003890 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003891 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003892 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003893 int err;
3894
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003895 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003896
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003897 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003898
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003899 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003900 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3901 MGMT_STATUS_NOT_POWERED,
3902 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003903 goto failed;
3904 }
3905
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003906 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3907 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003908 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3909 MGMT_STATUS_BUSY, &cp->type,
3910 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003911 goto failed;
3912 }
3913
Johan Hedberg2922a942014-12-05 13:36:06 +02003914 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003915 if (!cmd) {
3916 err = -ENOMEM;
3917 goto failed;
3918 }
3919
Johan Hedberg2922a942014-12-05 13:36:06 +02003920 cmd->cmd_complete = generic_cmd_complete;
3921
Marcel Holtmann22078802014-12-05 11:45:22 +01003922 /* Clear the discovery filter first to free any previously
3923 * allocated memory for the UUID list.
3924 */
3925 hci_discovery_filter_clear(hdev);
3926
Andre Guedes4aab14e2012-02-17 20:39:36 -03003927 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003928 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003929
Andre Guedes7c307722013-04-30 15:29:28 -03003930 hci_req_init(&req, hdev);
3931
Marcel Holtmann80190442014-12-04 11:36:36 +01003932 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003933 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003934 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003935 mgmt_pending_remove(cmd);
3936 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003937 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003938
Andre Guedes7c307722013-04-30 15:29:28 -03003939 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003940 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003941 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003942 goto failed;
3943 }
3944
3945 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003946
3947failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003948 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003949 return err;
3950}
3951
Johan Hedberg9df74652014-12-19 22:26:03 +02003952static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03003953{
Johan Hedberg9df74652014-12-19 22:26:03 +02003954 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
3955 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02003956}
3957
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003958static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3959 void *data, u16 len)
3960{
3961 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003962 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003963 struct hci_request req;
3964 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3965 u16 uuid_count, expected_len;
3966 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003967 int err;
3968
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003969 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003970
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003971 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003972
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003973 if (!hdev_is_powered(hdev)) {
3974 err = cmd_complete(sk, hdev->id,
3975 MGMT_OP_START_SERVICE_DISCOVERY,
3976 MGMT_STATUS_NOT_POWERED,
3977 &cp->type, sizeof(cp->type));
3978 goto failed;
3979 }
3980
3981 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3982 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3983 err = cmd_complete(sk, hdev->id,
3984 MGMT_OP_START_SERVICE_DISCOVERY,
3985 MGMT_STATUS_BUSY, &cp->type,
3986 sizeof(cp->type));
3987 goto failed;
3988 }
3989
3990 uuid_count = __le16_to_cpu(cp->uuid_count);
3991 if (uuid_count > max_uuid_count) {
3992 BT_ERR("service_discovery: too big uuid_count value %u",
3993 uuid_count);
3994 err = cmd_complete(sk, hdev->id,
3995 MGMT_OP_START_SERVICE_DISCOVERY,
3996 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3997 sizeof(cp->type));
3998 goto failed;
3999 }
4000
4001 expected_len = sizeof(*cp) + uuid_count * 16;
4002 if (expected_len != len) {
4003 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4004 expected_len, len);
4005 err = cmd_complete(sk, hdev->id,
4006 MGMT_OP_START_SERVICE_DISCOVERY,
4007 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4008 sizeof(cp->type));
4009 goto failed;
4010 }
4011
4012 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004013 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004014 if (!cmd) {
4015 err = -ENOMEM;
4016 goto failed;
4017 }
4018
Johan Hedberg2922a942014-12-05 13:36:06 +02004019 cmd->cmd_complete = service_discovery_cmd_complete;
4020
Marcel Holtmann22078802014-12-05 11:45:22 +01004021 /* Clear the discovery filter first to free any previously
4022 * allocated memory for the UUID list.
4023 */
4024 hci_discovery_filter_clear(hdev);
4025
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004026 hdev->discovery.type = cp->type;
4027 hdev->discovery.rssi = cp->rssi;
4028 hdev->discovery.uuid_count = uuid_count;
4029
4030 if (uuid_count > 0) {
4031 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4032 GFP_KERNEL);
4033 if (!hdev->discovery.uuids) {
4034 err = cmd_complete(sk, hdev->id,
4035 MGMT_OP_START_SERVICE_DISCOVERY,
4036 MGMT_STATUS_FAILED,
4037 &cp->type, sizeof(cp->type));
4038 mgmt_pending_remove(cmd);
4039 goto failed;
4040 }
4041 }
4042
4043 hci_req_init(&req, hdev);
4044
4045 if (!trigger_discovery(&req, &status)) {
4046 err = cmd_complete(sk, hdev->id,
4047 MGMT_OP_START_SERVICE_DISCOVERY,
4048 status, &cp->type, sizeof(cp->type));
4049 mgmt_pending_remove(cmd);
4050 goto failed;
4051 }
4052
4053 err = hci_req_run(&req, start_discovery_complete);
4054 if (err < 0) {
4055 mgmt_pending_remove(cmd);
4056 goto failed;
4057 }
4058
4059 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4060
4061failed:
4062 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004063 return err;
4064}
4065
Andre Guedes0e05bba2013-04-30 15:29:33 -03004066static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4067{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004068 struct pending_cmd *cmd;
4069
Andre Guedes0e05bba2013-04-30 15:29:33 -03004070 BT_DBG("status %d", status);
4071
4072 hci_dev_lock(hdev);
4073
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004074 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4075 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004076 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004077 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004078 }
4079
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004080 if (!status)
4081 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004082
Andre Guedes0e05bba2013-04-30 15:29:33 -03004083 hci_dev_unlock(hdev);
4084}
4085
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004086static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004087 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004088{
Johan Hedbergd9306502012-02-20 23:25:18 +02004089 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004090 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004091 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004092 int err;
4093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004094 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004095
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004096 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004097
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004098 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004099 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004100 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4101 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004102 goto unlock;
4103 }
4104
4105 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004106 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004107 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4108 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004109 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004110 }
4111
Johan Hedberg2922a942014-12-05 13:36:06 +02004112 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004113 if (!cmd) {
4114 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004115 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004116 }
4117
Johan Hedberg2922a942014-12-05 13:36:06 +02004118 cmd->cmd_complete = generic_cmd_complete;
4119
Andre Guedes0e05bba2013-04-30 15:29:33 -03004120 hci_req_init(&req, hdev);
4121
Johan Hedberg21a60d32014-06-10 14:05:58 +03004122 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004123
Johan Hedberg21a60d32014-06-10 14:05:58 +03004124 err = hci_req_run(&req, stop_discovery_complete);
4125 if (!err) {
4126 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004127 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004128 }
4129
Johan Hedberg21a60d32014-06-10 14:05:58 +03004130 mgmt_pending_remove(cmd);
4131
4132 /* If no HCI commands were sent we're done */
4133 if (err == -ENODATA) {
4134 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4135 &mgmt_cp->type, sizeof(mgmt_cp->type));
4136 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4137 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004138
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004139unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004140 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004141 return err;
4142}
4143
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004144static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004145 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004146{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004147 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004148 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004149 int err;
4150
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004151 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004152
Johan Hedberg561aafb2012-01-04 13:31:59 +02004153 hci_dev_lock(hdev);
4154
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004155 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004156 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4157 MGMT_STATUS_FAILED, &cp->addr,
4158 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004159 goto failed;
4160 }
4161
Johan Hedberga198e7b2012-02-17 14:27:06 +02004162 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004163 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004164 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4165 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4166 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004167 goto failed;
4168 }
4169
4170 if (cp->name_known) {
4171 e->name_state = NAME_KNOWN;
4172 list_del(&e->list);
4173 } else {
4174 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004175 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004176 }
4177
Johan Hedberge3846622013-01-09 15:29:33 +02004178 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4179 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004180
4181failed:
4182 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004183 return err;
4184}
4185
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004186static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004187 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004188{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004189 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004190 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004191 int err;
4192
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004193 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004194
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004195 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004196 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4197 MGMT_STATUS_INVALID_PARAMS,
4198 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004199
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004200 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004201
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004202 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4203 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004204 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004205 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004206 goto done;
4207 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004208
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004209 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4210 sk);
4211 status = MGMT_STATUS_SUCCESS;
4212
4213done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004214 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004215 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004216
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004217 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004218
4219 return err;
4220}
4221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004222static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004223 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004224{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004225 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004226 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004227 int err;
4228
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004229 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004230
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004231 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004232 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4233 MGMT_STATUS_INVALID_PARAMS,
4234 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004235
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004236 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004237
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004238 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4239 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004240 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004241 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004242 goto done;
4243 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004244
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004245 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4246 sk);
4247 status = MGMT_STATUS_SUCCESS;
4248
4249done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004250 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004251 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004252
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004253 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004254
4255 return err;
4256}
4257
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004258static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4259 u16 len)
4260{
4261 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004262 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004263 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004264 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004265
4266 BT_DBG("%s", hdev->name);
4267
Szymon Jancc72d4b82012-03-16 16:02:57 +01004268 source = __le16_to_cpu(cp->source);
4269
4270 if (source > 0x0002)
4271 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4272 MGMT_STATUS_INVALID_PARAMS);
4273
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004274 hci_dev_lock(hdev);
4275
Szymon Jancc72d4b82012-03-16 16:02:57 +01004276 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004277 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4278 hdev->devid_product = __le16_to_cpu(cp->product);
4279 hdev->devid_version = __le16_to_cpu(cp->version);
4280
4281 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4282
Johan Hedberg890ea892013-03-15 17:06:52 -05004283 hci_req_init(&req, hdev);
4284 update_eir(&req);
4285 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004286
4287 hci_dev_unlock(hdev);
4288
4289 return err;
4290}
4291
Johan Hedberg4375f102013-09-25 13:26:10 +03004292static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4293{
4294 struct cmd_lookup match = { NULL, hdev };
4295
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304296 hci_dev_lock(hdev);
4297
Johan Hedberg4375f102013-09-25 13:26:10 +03004298 if (status) {
4299 u8 mgmt_err = mgmt_status(status);
4300
4301 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4302 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304303 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004304 }
4305
Johan Hedbergc93bd152014-07-08 15:07:48 +03004306 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4307 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4308 else
4309 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4310
Johan Hedberg4375f102013-09-25 13:26:10 +03004311 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4312 &match);
4313
4314 new_settings(hdev, match.sk);
4315
4316 if (match.sk)
4317 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304318
4319unlock:
4320 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004321}
4322
Marcel Holtmann21b51872013-10-10 09:47:53 -07004323static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4324 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004325{
4326 struct mgmt_mode *cp = data;
4327 struct pending_cmd *cmd;
4328 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004329 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004330 int err;
4331
4332 BT_DBG("request for %s", hdev->name);
4333
Johan Hedberge6fe7982013-10-02 15:45:22 +03004334 status = mgmt_le_support(hdev);
4335 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004336 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004337 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004338
4339 if (cp->val != 0x00 && cp->val != 0x01)
4340 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4341 MGMT_STATUS_INVALID_PARAMS);
4342
4343 hci_dev_lock(hdev);
4344
4345 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004346 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004347
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004348 /* The following conditions are ones which mean that we should
4349 * not do any HCI communication but directly send a mgmt
4350 * response to user space (after toggling the flag if
4351 * necessary).
4352 */
4353 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004354 hci_conn_num(hdev, LE_LINK) > 0 ||
4355 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4356 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004357 bool changed = false;
4358
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004359 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4360 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004361 changed = true;
4362 }
4363
4364 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4365 if (err < 0)
4366 goto unlock;
4367
4368 if (changed)
4369 err = new_settings(hdev, sk);
4370
4371 goto unlock;
4372 }
4373
4374 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4375 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4376 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4377 MGMT_STATUS_BUSY);
4378 goto unlock;
4379 }
4380
4381 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4382 if (!cmd) {
4383 err = -ENOMEM;
4384 goto unlock;
4385 }
4386
4387 hci_req_init(&req, hdev);
4388
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004389 if (val)
4390 enable_advertising(&req);
4391 else
4392 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004393
4394 err = hci_req_run(&req, set_advertising_complete);
4395 if (err < 0)
4396 mgmt_pending_remove(cmd);
4397
4398unlock:
4399 hci_dev_unlock(hdev);
4400 return err;
4401}
4402
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004403static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4404 void *data, u16 len)
4405{
4406 struct mgmt_cp_set_static_address *cp = data;
4407 int err;
4408
4409 BT_DBG("%s", hdev->name);
4410
Marcel Holtmann62af4442013-10-02 22:10:32 -07004411 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004412 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004413 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004414
4415 if (hdev_is_powered(hdev))
4416 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4417 MGMT_STATUS_REJECTED);
4418
4419 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4420 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4421 return cmd_status(sk, hdev->id,
4422 MGMT_OP_SET_STATIC_ADDRESS,
4423 MGMT_STATUS_INVALID_PARAMS);
4424
4425 /* Two most significant bits shall be set */
4426 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4427 return cmd_status(sk, hdev->id,
4428 MGMT_OP_SET_STATIC_ADDRESS,
4429 MGMT_STATUS_INVALID_PARAMS);
4430 }
4431
4432 hci_dev_lock(hdev);
4433
4434 bacpy(&hdev->static_addr, &cp->bdaddr);
4435
4436 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4437
4438 hci_dev_unlock(hdev);
4439
4440 return err;
4441}
4442
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004443static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4444 void *data, u16 len)
4445{
4446 struct mgmt_cp_set_scan_params *cp = data;
4447 __u16 interval, window;
4448 int err;
4449
4450 BT_DBG("%s", hdev->name);
4451
4452 if (!lmp_le_capable(hdev))
4453 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4454 MGMT_STATUS_NOT_SUPPORTED);
4455
4456 interval = __le16_to_cpu(cp->interval);
4457
4458 if (interval < 0x0004 || interval > 0x4000)
4459 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4460 MGMT_STATUS_INVALID_PARAMS);
4461
4462 window = __le16_to_cpu(cp->window);
4463
4464 if (window < 0x0004 || window > 0x4000)
4465 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4466 MGMT_STATUS_INVALID_PARAMS);
4467
Marcel Holtmann899e1072013-10-14 09:55:32 -07004468 if (window > interval)
4469 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4470 MGMT_STATUS_INVALID_PARAMS);
4471
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004472 hci_dev_lock(hdev);
4473
4474 hdev->le_scan_interval = interval;
4475 hdev->le_scan_window = window;
4476
4477 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4478
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004479 /* If background scan is running, restart it so new parameters are
4480 * loaded.
4481 */
4482 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4483 hdev->discovery.state == DISCOVERY_STOPPED) {
4484 struct hci_request req;
4485
4486 hci_req_init(&req, hdev);
4487
4488 hci_req_add_le_scan_disable(&req);
4489 hci_req_add_le_passive_scan(&req);
4490
4491 hci_req_run(&req, NULL);
4492 }
4493
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004494 hci_dev_unlock(hdev);
4495
4496 return err;
4497}
4498
Johan Hedberg33e38b32013-03-15 17:07:05 -05004499static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4500{
4501 struct pending_cmd *cmd;
4502
4503 BT_DBG("status 0x%02x", status);
4504
4505 hci_dev_lock(hdev);
4506
4507 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4508 if (!cmd)
4509 goto unlock;
4510
4511 if (status) {
4512 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4513 mgmt_status(status));
4514 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004515 struct mgmt_mode *cp = cmd->param;
4516
4517 if (cp->val)
4518 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4519 else
4520 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4521
Johan Hedberg33e38b32013-03-15 17:07:05 -05004522 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4523 new_settings(hdev, cmd->sk);
4524 }
4525
4526 mgmt_pending_remove(cmd);
4527
4528unlock:
4529 hci_dev_unlock(hdev);
4530}
4531
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004532static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004533 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004534{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004535 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004536 struct pending_cmd *cmd;
4537 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004538 int err;
4539
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004540 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004541
Johan Hedberg56f87902013-10-02 13:43:13 +03004542 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4543 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004544 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4545 MGMT_STATUS_NOT_SUPPORTED);
4546
Johan Hedberga7e80f22013-01-09 16:05:19 +02004547 if (cp->val != 0x00 && cp->val != 0x01)
4548 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4549 MGMT_STATUS_INVALID_PARAMS);
4550
Johan Hedberg5400c042012-02-21 16:40:33 +02004551 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004552 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004553 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004554
4555 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004556 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004557 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004558
4559 hci_dev_lock(hdev);
4560
Johan Hedberg05cbf292013-03-15 17:07:07 -05004561 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4562 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4563 MGMT_STATUS_BUSY);
4564 goto unlock;
4565 }
4566
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004567 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4568 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4569 hdev);
4570 goto unlock;
4571 }
4572
Johan Hedberg33e38b32013-03-15 17:07:05 -05004573 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4574 data, len);
4575 if (!cmd) {
4576 err = -ENOMEM;
4577 goto unlock;
4578 }
4579
4580 hci_req_init(&req, hdev);
4581
Johan Hedberg406d7802013-03-15 17:07:09 -05004582 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004583
4584 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004585 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004586 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004587 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004588 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004589 }
4590
Johan Hedberg33e38b32013-03-15 17:07:05 -05004591unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004592 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004593
Antti Julkuf6422ec2011-06-22 13:11:56 +03004594 return err;
4595}
4596
Johan Hedberg0663ca22013-10-02 13:43:14 +03004597static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4598{
4599 struct pending_cmd *cmd;
4600
4601 BT_DBG("status 0x%02x", status);
4602
4603 hci_dev_lock(hdev);
4604
4605 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4606 if (!cmd)
4607 goto unlock;
4608
4609 if (status) {
4610 u8 mgmt_err = mgmt_status(status);
4611
4612 /* We need to restore the flag if related HCI commands
4613 * failed.
4614 */
4615 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4616
4617 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4618 } else {
4619 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4620 new_settings(hdev, cmd->sk);
4621 }
4622
4623 mgmt_pending_remove(cmd);
4624
4625unlock:
4626 hci_dev_unlock(hdev);
4627}
4628
4629static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4630{
4631 struct mgmt_mode *cp = data;
4632 struct pending_cmd *cmd;
4633 struct hci_request req;
4634 int err;
4635
4636 BT_DBG("request for %s", hdev->name);
4637
4638 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4639 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4640 MGMT_STATUS_NOT_SUPPORTED);
4641
4642 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4643 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4644 MGMT_STATUS_REJECTED);
4645
4646 if (cp->val != 0x00 && cp->val != 0x01)
4647 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4648 MGMT_STATUS_INVALID_PARAMS);
4649
4650 hci_dev_lock(hdev);
4651
4652 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4653 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4654 goto unlock;
4655 }
4656
4657 if (!hdev_is_powered(hdev)) {
4658 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004659 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4660 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4661 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4662 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4663 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4664 }
4665
4666 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4667
4668 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4669 if (err < 0)
4670 goto unlock;
4671
4672 err = new_settings(hdev, sk);
4673 goto unlock;
4674 }
4675
4676 /* Reject disabling when powered on */
4677 if (!cp->val) {
4678 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4679 MGMT_STATUS_REJECTED);
4680 goto unlock;
4681 }
4682
4683 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4684 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4685 MGMT_STATUS_BUSY);
4686 goto unlock;
4687 }
4688
4689 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4690 if (!cmd) {
4691 err = -ENOMEM;
4692 goto unlock;
4693 }
4694
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004695 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004696 * generates the correct flags.
4697 */
4698 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4699
4700 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004701
Johan Hedberg432df052014-08-01 11:13:31 +03004702 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004703 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004704
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004705 /* Since only the advertising data flags will change, there
4706 * is no need to update the scan response data.
4707 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004708 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004709
Johan Hedberg0663ca22013-10-02 13:43:14 +03004710 err = hci_req_run(&req, set_bredr_complete);
4711 if (err < 0)
4712 mgmt_pending_remove(cmd);
4713
4714unlock:
4715 hci_dev_unlock(hdev);
4716 return err;
4717}
4718
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004719static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4720 void *data, u16 len)
4721{
4722 struct mgmt_mode *cp = data;
4723 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004724 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004725 int err;
4726
4727 BT_DBG("request for %s", hdev->name);
4728
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004729 if (!lmp_sc_capable(hdev) &&
4730 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004731 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4732 MGMT_STATUS_NOT_SUPPORTED);
4733
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004734 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004735 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4736 MGMT_STATUS_INVALID_PARAMS);
4737
4738 hci_dev_lock(hdev);
4739
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004740 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004741 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004742 bool changed;
4743
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004744 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004745 changed = !test_and_set_bit(HCI_SC_ENABLED,
4746 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004747 if (cp->val == 0x02)
4748 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4749 else
4750 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4751 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004752 changed = test_and_clear_bit(HCI_SC_ENABLED,
4753 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004754 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4755 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004756
4757 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4758 if (err < 0)
4759 goto failed;
4760
4761 if (changed)
4762 err = new_settings(hdev, sk);
4763
4764 goto failed;
4765 }
4766
4767 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4768 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4769 MGMT_STATUS_BUSY);
4770 goto failed;
4771 }
4772
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004773 val = !!cp->val;
4774
4775 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4776 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004777 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4778 goto failed;
4779 }
4780
4781 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4782 if (!cmd) {
4783 err = -ENOMEM;
4784 goto failed;
4785 }
4786
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004787 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004788 if (err < 0) {
4789 mgmt_pending_remove(cmd);
4790 goto failed;
4791 }
4792
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004793 if (cp->val == 0x02)
4794 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4795 else
4796 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4797
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004798failed:
4799 hci_dev_unlock(hdev);
4800 return err;
4801}
4802
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004803static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4804 void *data, u16 len)
4805{
4806 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004807 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004808 int err;
4809
4810 BT_DBG("request for %s", hdev->name);
4811
Johan Hedbergb97109792014-06-24 14:00:28 +03004812 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004813 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4814 MGMT_STATUS_INVALID_PARAMS);
4815
4816 hci_dev_lock(hdev);
4817
4818 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004819 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4820 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004821 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004822 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4823 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004824
Johan Hedbergb97109792014-06-24 14:00:28 +03004825 if (cp->val == 0x02)
4826 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4827 &hdev->dev_flags);
4828 else
4829 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4830 &hdev->dev_flags);
4831
4832 if (hdev_is_powered(hdev) && use_changed &&
4833 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4834 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4835 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4836 sizeof(mode), &mode);
4837 }
4838
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004839 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4840 if (err < 0)
4841 goto unlock;
4842
4843 if (changed)
4844 err = new_settings(hdev, sk);
4845
4846unlock:
4847 hci_dev_unlock(hdev);
4848 return err;
4849}
4850
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004851static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4852 u16 len)
4853{
4854 struct mgmt_cp_set_privacy *cp = cp_data;
4855 bool changed;
4856 int err;
4857
4858 BT_DBG("request for %s", hdev->name);
4859
4860 if (!lmp_le_capable(hdev))
4861 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4862 MGMT_STATUS_NOT_SUPPORTED);
4863
4864 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4865 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4866 MGMT_STATUS_INVALID_PARAMS);
4867
4868 if (hdev_is_powered(hdev))
4869 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4870 MGMT_STATUS_REJECTED);
4871
4872 hci_dev_lock(hdev);
4873
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004874 /* If user space supports this command it is also expected to
4875 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4876 */
4877 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4878
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004879 if (cp->privacy) {
4880 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4881 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4882 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4883 } else {
4884 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4885 memset(hdev->irk, 0, sizeof(hdev->irk));
4886 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4887 }
4888
4889 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4890 if (err < 0)
4891 goto unlock;
4892
4893 if (changed)
4894 err = new_settings(hdev, sk);
4895
4896unlock:
4897 hci_dev_unlock(hdev);
4898 return err;
4899}
4900
Johan Hedberg41edf162014-02-18 10:19:35 +02004901static bool irk_is_valid(struct mgmt_irk_info *irk)
4902{
4903 switch (irk->addr.type) {
4904 case BDADDR_LE_PUBLIC:
4905 return true;
4906
4907 case BDADDR_LE_RANDOM:
4908 /* Two most significant bits shall be set */
4909 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4910 return false;
4911 return true;
4912 }
4913
4914 return false;
4915}
4916
4917static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4918 u16 len)
4919{
4920 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004921 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4922 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004923 u16 irk_count, expected_len;
4924 int i, err;
4925
4926 BT_DBG("request for %s", hdev->name);
4927
4928 if (!lmp_le_capable(hdev))
4929 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4930 MGMT_STATUS_NOT_SUPPORTED);
4931
4932 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004933 if (irk_count > max_irk_count) {
4934 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4935 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4936 MGMT_STATUS_INVALID_PARAMS);
4937 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004938
4939 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4940 if (expected_len != len) {
4941 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004942 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004943 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4944 MGMT_STATUS_INVALID_PARAMS);
4945 }
4946
4947 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4948
4949 for (i = 0; i < irk_count; i++) {
4950 struct mgmt_irk_info *key = &cp->irks[i];
4951
4952 if (!irk_is_valid(key))
4953 return cmd_status(sk, hdev->id,
4954 MGMT_OP_LOAD_IRKS,
4955 MGMT_STATUS_INVALID_PARAMS);
4956 }
4957
4958 hci_dev_lock(hdev);
4959
4960 hci_smp_irks_clear(hdev);
4961
4962 for (i = 0; i < irk_count; i++) {
4963 struct mgmt_irk_info *irk = &cp->irks[i];
4964 u8 addr_type;
4965
4966 if (irk->addr.type == BDADDR_LE_PUBLIC)
4967 addr_type = ADDR_LE_DEV_PUBLIC;
4968 else
4969 addr_type = ADDR_LE_DEV_RANDOM;
4970
4971 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4972 BDADDR_ANY);
4973 }
4974
4975 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4976
4977 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4978
4979 hci_dev_unlock(hdev);
4980
4981 return err;
4982}
4983
Johan Hedberg3f706b72013-01-20 14:27:16 +02004984static bool ltk_is_valid(struct mgmt_ltk_info *key)
4985{
4986 if (key->master != 0x00 && key->master != 0x01)
4987 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004988
4989 switch (key->addr.type) {
4990 case BDADDR_LE_PUBLIC:
4991 return true;
4992
4993 case BDADDR_LE_RANDOM:
4994 /* Two most significant bits shall be set */
4995 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4996 return false;
4997 return true;
4998 }
4999
5000 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005001}
5002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005003static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005004 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005005{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005006 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005007 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5008 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005009 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005010 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005011
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005012 BT_DBG("request for %s", hdev->name);
5013
5014 if (!lmp_le_capable(hdev))
5015 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5016 MGMT_STATUS_NOT_SUPPORTED);
5017
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005018 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005019 if (key_count > max_key_count) {
5020 BT_ERR("load_ltks: too big key_count value %u", key_count);
5021 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5022 MGMT_STATUS_INVALID_PARAMS);
5023 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005024
5025 expected_len = sizeof(*cp) + key_count *
5026 sizeof(struct mgmt_ltk_info);
5027 if (expected_len != len) {
5028 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005029 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005030 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005031 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005032 }
5033
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005034 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005035
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005036 for (i = 0; i < key_count; i++) {
5037 struct mgmt_ltk_info *key = &cp->keys[i];
5038
Johan Hedberg3f706b72013-01-20 14:27:16 +02005039 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005040 return cmd_status(sk, hdev->id,
5041 MGMT_OP_LOAD_LONG_TERM_KEYS,
5042 MGMT_STATUS_INVALID_PARAMS);
5043 }
5044
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005045 hci_dev_lock(hdev);
5046
5047 hci_smp_ltks_clear(hdev);
5048
5049 for (i = 0; i < key_count; i++) {
5050 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005051 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005052
5053 if (key->addr.type == BDADDR_LE_PUBLIC)
5054 addr_type = ADDR_LE_DEV_PUBLIC;
5055 else
5056 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005057
Johan Hedberg61b43352014-05-29 19:36:53 +03005058 switch (key->type) {
5059 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005060 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005061 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005062 break;
5063 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005064 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005065 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005066 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005067 case MGMT_LTK_P256_UNAUTH:
5068 authenticated = 0x00;
5069 type = SMP_LTK_P256;
5070 break;
5071 case MGMT_LTK_P256_AUTH:
5072 authenticated = 0x01;
5073 type = SMP_LTK_P256;
5074 break;
5075 case MGMT_LTK_P256_DEBUG:
5076 authenticated = 0x00;
5077 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005078 default:
5079 continue;
5080 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005081
Johan Hedberg35d70272014-02-19 14:57:47 +02005082 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005083 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005084 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005085 }
5086
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005087 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5088 NULL, 0);
5089
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005090 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005091
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005092 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005093}
5094
Johan Hedberg9df74652014-12-19 22:26:03 +02005095static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005096{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005097 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005098 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005099 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005100
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005101 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005102
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005103 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005104 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005105 rp.tx_power = conn->tx_power;
5106 rp.max_tx_power = conn->max_tx_power;
5107 } else {
5108 rp.rssi = HCI_RSSI_INVALID;
5109 rp.tx_power = HCI_TX_POWER_INVALID;
5110 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005111 }
5112
Johan Hedberg9df74652014-12-19 22:26:03 +02005113 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5114 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005115
5116 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005117 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005118
5119 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005120}
5121
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005122static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005123{
5124 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005125 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005126 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005127 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005128 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005129
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005130 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005131
5132 hci_dev_lock(hdev);
5133
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005134 /* Commands sent in request are either Read RSSI or Read Transmit Power
5135 * Level so we check which one was last sent to retrieve connection
5136 * handle. Both commands have handle as first parameter so it's safe to
5137 * cast data on the same command struct.
5138 *
5139 * First command sent is always Read RSSI and we fail only if it fails.
5140 * In other case we simply override error to indicate success as we
5141 * already remembered if TX power value is actually valid.
5142 */
5143 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5144 if (!cp) {
5145 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005146 status = MGMT_STATUS_SUCCESS;
5147 } else {
5148 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005149 }
5150
5151 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005152 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005153 goto unlock;
5154 }
5155
5156 handle = __le16_to_cpu(cp->handle);
5157 conn = hci_conn_hash_lookup_handle(hdev, handle);
5158 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005159 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005160 goto unlock;
5161 }
5162
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005163 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5164 if (!cmd)
5165 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005166
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005167 cmd->cmd_complete(cmd, status);
5168 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005169
5170unlock:
5171 hci_dev_unlock(hdev);
5172}
5173
5174static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5175 u16 len)
5176{
5177 struct mgmt_cp_get_conn_info *cp = data;
5178 struct mgmt_rp_get_conn_info rp;
5179 struct hci_conn *conn;
5180 unsigned long conn_info_age;
5181 int err = 0;
5182
5183 BT_DBG("%s", hdev->name);
5184
5185 memset(&rp, 0, sizeof(rp));
5186 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5187 rp.addr.type = cp->addr.type;
5188
5189 if (!bdaddr_type_is_valid(cp->addr.type))
5190 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5191 MGMT_STATUS_INVALID_PARAMS,
5192 &rp, sizeof(rp));
5193
5194 hci_dev_lock(hdev);
5195
5196 if (!hdev_is_powered(hdev)) {
5197 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5198 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5199 goto unlock;
5200 }
5201
5202 if (cp->addr.type == BDADDR_BREDR)
5203 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5204 &cp->addr.bdaddr);
5205 else
5206 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5207
5208 if (!conn || conn->state != BT_CONNECTED) {
5209 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5210 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5211 goto unlock;
5212 }
5213
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005214 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5215 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5216 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5217 goto unlock;
5218 }
5219
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005220 /* To avoid client trying to guess when to poll again for information we
5221 * calculate conn info age as random value between min/max set in hdev.
5222 */
5223 conn_info_age = hdev->conn_info_min_age +
5224 prandom_u32_max(hdev->conn_info_max_age -
5225 hdev->conn_info_min_age);
5226
5227 /* Query controller to refresh cached values if they are too old or were
5228 * never read.
5229 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005230 if (time_after(jiffies, conn->conn_info_timestamp +
5231 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005232 !conn->conn_info_timestamp) {
5233 struct hci_request req;
5234 struct hci_cp_read_tx_power req_txp_cp;
5235 struct hci_cp_read_rssi req_rssi_cp;
5236 struct pending_cmd *cmd;
5237
5238 hci_req_init(&req, hdev);
5239 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5240 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5241 &req_rssi_cp);
5242
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005243 /* For LE links TX power does not change thus we don't need to
5244 * query for it once value is known.
5245 */
5246 if (!bdaddr_type_is_le(cp->addr.type) ||
5247 conn->tx_power == HCI_TX_POWER_INVALID) {
5248 req_txp_cp.handle = cpu_to_le16(conn->handle);
5249 req_txp_cp.type = 0x00;
5250 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5251 sizeof(req_txp_cp), &req_txp_cp);
5252 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005253
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005254 /* Max TX power needs to be read only once per connection */
5255 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5256 req_txp_cp.handle = cpu_to_le16(conn->handle);
5257 req_txp_cp.type = 0x01;
5258 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5259 sizeof(req_txp_cp), &req_txp_cp);
5260 }
5261
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005262 err = hci_req_run(&req, conn_info_refresh_complete);
5263 if (err < 0)
5264 goto unlock;
5265
5266 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5267 data, len);
5268 if (!cmd) {
5269 err = -ENOMEM;
5270 goto unlock;
5271 }
5272
5273 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005274 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005275 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005276
5277 conn->conn_info_timestamp = jiffies;
5278 } else {
5279 /* Cache is valid, just reply with values cached in hci_conn */
5280 rp.rssi = conn->rssi;
5281 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005282 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005283
5284 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5285 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5286 }
5287
5288unlock:
5289 hci_dev_unlock(hdev);
5290 return err;
5291}
5292
Johan Hedberg9df74652014-12-19 22:26:03 +02005293static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005294{
5295 struct hci_conn *conn = cmd->user_data;
5296 struct mgmt_rp_get_clock_info rp;
5297 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005298 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005299
5300 memset(&rp, 0, sizeof(rp));
5301 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5302
5303 if (status)
5304 goto complete;
5305
5306 hdev = hci_dev_get(cmd->index);
5307 if (hdev) {
5308 rp.local_clock = cpu_to_le32(hdev->clock);
5309 hci_dev_put(hdev);
5310 }
5311
5312 if (conn) {
5313 rp.piconet_clock = cpu_to_le32(conn->clock);
5314 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5315 }
5316
5317complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005318 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5319 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005320
5321 if (conn) {
5322 hci_conn_drop(conn);
5323 hci_conn_put(conn);
5324 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005325
5326 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005327}
5328
Johan Hedberg95868422014-06-28 17:54:07 +03005329static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5330{
Johan Hedberg95868422014-06-28 17:54:07 +03005331 struct hci_cp_read_clock *hci_cp;
5332 struct pending_cmd *cmd;
5333 struct hci_conn *conn;
5334
5335 BT_DBG("%s status %u", hdev->name, status);
5336
5337 hci_dev_lock(hdev);
5338
5339 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5340 if (!hci_cp)
5341 goto unlock;
5342
5343 if (hci_cp->which) {
5344 u16 handle = __le16_to_cpu(hci_cp->handle);
5345 conn = hci_conn_hash_lookup_handle(hdev, handle);
5346 } else {
5347 conn = NULL;
5348 }
5349
5350 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5351 if (!cmd)
5352 goto unlock;
5353
Johan Hedberg69487372014-12-05 13:36:07 +02005354 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005355 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005356
5357unlock:
5358 hci_dev_unlock(hdev);
5359}
5360
5361static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5362 u16 len)
5363{
5364 struct mgmt_cp_get_clock_info *cp = data;
5365 struct mgmt_rp_get_clock_info rp;
5366 struct hci_cp_read_clock hci_cp;
5367 struct pending_cmd *cmd;
5368 struct hci_request req;
5369 struct hci_conn *conn;
5370 int err;
5371
5372 BT_DBG("%s", hdev->name);
5373
5374 memset(&rp, 0, sizeof(rp));
5375 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5376 rp.addr.type = cp->addr.type;
5377
5378 if (cp->addr.type != BDADDR_BREDR)
5379 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5380 MGMT_STATUS_INVALID_PARAMS,
5381 &rp, sizeof(rp));
5382
5383 hci_dev_lock(hdev);
5384
5385 if (!hdev_is_powered(hdev)) {
5386 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5387 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5388 goto unlock;
5389 }
5390
5391 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5392 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5393 &cp->addr.bdaddr);
5394 if (!conn || conn->state != BT_CONNECTED) {
5395 err = cmd_complete(sk, hdev->id,
5396 MGMT_OP_GET_CLOCK_INFO,
5397 MGMT_STATUS_NOT_CONNECTED,
5398 &rp, sizeof(rp));
5399 goto unlock;
5400 }
5401 } else {
5402 conn = NULL;
5403 }
5404
5405 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5406 if (!cmd) {
5407 err = -ENOMEM;
5408 goto unlock;
5409 }
5410
Johan Hedberg69487372014-12-05 13:36:07 +02005411 cmd->cmd_complete = clock_info_cmd_complete;
5412
Johan Hedberg95868422014-06-28 17:54:07 +03005413 hci_req_init(&req, hdev);
5414
5415 memset(&hci_cp, 0, sizeof(hci_cp));
5416 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5417
5418 if (conn) {
5419 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005420 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005421
5422 hci_cp.handle = cpu_to_le16(conn->handle);
5423 hci_cp.which = 0x01; /* Piconet clock */
5424 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5425 }
5426
5427 err = hci_req_run(&req, get_clock_info_complete);
5428 if (err < 0)
5429 mgmt_pending_remove(cmd);
5430
5431unlock:
5432 hci_dev_unlock(hdev);
5433 return err;
5434}
5435
Johan Hedberg5a154e62014-12-19 22:26:02 +02005436static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5437{
5438 struct hci_conn *conn;
5439
5440 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5441 if (!conn)
5442 return false;
5443
5444 if (conn->dst_type != type)
5445 return false;
5446
5447 if (conn->state != BT_CONNECTED)
5448 return false;
5449
5450 return true;
5451}
5452
5453/* This function requires the caller holds hdev->lock */
5454static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5455 u8 addr_type, u8 auto_connect)
5456{
5457 struct hci_dev *hdev = req->hdev;
5458 struct hci_conn_params *params;
5459
5460 params = hci_conn_params_add(hdev, addr, addr_type);
5461 if (!params)
5462 return -EIO;
5463
5464 if (params->auto_connect == auto_connect)
5465 return 0;
5466
5467 list_del_init(&params->action);
5468
5469 switch (auto_connect) {
5470 case HCI_AUTO_CONN_DISABLED:
5471 case HCI_AUTO_CONN_LINK_LOSS:
5472 __hci_update_background_scan(req);
5473 break;
5474 case HCI_AUTO_CONN_REPORT:
5475 list_add(&params->action, &hdev->pend_le_reports);
5476 __hci_update_background_scan(req);
5477 break;
5478 case HCI_AUTO_CONN_DIRECT:
5479 case HCI_AUTO_CONN_ALWAYS:
5480 if (!is_connected(hdev, addr, addr_type)) {
5481 list_add(&params->action, &hdev->pend_le_conns);
5482 __hci_update_background_scan(req);
5483 }
5484 break;
5485 }
5486
5487 params->auto_connect = auto_connect;
5488
5489 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5490 auto_connect);
5491
5492 return 0;
5493}
5494
Marcel Holtmann8afef092014-06-29 22:28:34 +02005495static void device_added(struct sock *sk, struct hci_dev *hdev,
5496 bdaddr_t *bdaddr, u8 type, u8 action)
5497{
5498 struct mgmt_ev_device_added ev;
5499
5500 bacpy(&ev.addr.bdaddr, bdaddr);
5501 ev.addr.type = type;
5502 ev.action = action;
5503
5504 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5505}
5506
Johan Hedberg5a154e62014-12-19 22:26:02 +02005507static void add_device_complete(struct hci_dev *hdev, u8 status)
5508{
5509 struct pending_cmd *cmd;
5510
5511 BT_DBG("status 0x%02x", status);
5512
5513 hci_dev_lock(hdev);
5514
5515 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5516 if (!cmd)
5517 goto unlock;
5518
5519 cmd->cmd_complete(cmd, mgmt_status(status));
5520 mgmt_pending_remove(cmd);
5521
5522unlock:
5523 hci_dev_unlock(hdev);
5524}
5525
Marcel Holtmann2faade52014-06-29 19:44:03 +02005526static int add_device(struct sock *sk, struct hci_dev *hdev,
5527 void *data, u16 len)
5528{
5529 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005530 struct pending_cmd *cmd;
5531 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005532 u8 auto_conn, addr_type;
5533 int err;
5534
5535 BT_DBG("%s", hdev->name);
5536
Johan Hedberg66593582014-07-09 12:59:14 +03005537 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005538 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5539 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5540 MGMT_STATUS_INVALID_PARAMS,
5541 &cp->addr, sizeof(cp->addr));
5542
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005543 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005544 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5545 MGMT_STATUS_INVALID_PARAMS,
5546 &cp->addr, sizeof(cp->addr));
5547
Johan Hedberg5a154e62014-12-19 22:26:02 +02005548 hci_req_init(&req, hdev);
5549
Marcel Holtmann2faade52014-06-29 19:44:03 +02005550 hci_dev_lock(hdev);
5551
Johan Hedberg5a154e62014-12-19 22:26:02 +02005552 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5553 if (!cmd) {
5554 err = -ENOMEM;
5555 goto unlock;
5556 }
5557
5558 cmd->cmd_complete = addr_cmd_complete;
5559
Johan Hedberg66593582014-07-09 12:59:14 +03005560 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005561 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005562 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005563 err = cmd->cmd_complete(cmd,
5564 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005565 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005566 goto unlock;
5567 }
5568
5569 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5570 cp->addr.type);
5571 if (err)
5572 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005573
Johan Hedberg5a154e62014-12-19 22:26:02 +02005574 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005575
Johan Hedberg66593582014-07-09 12:59:14 +03005576 goto added;
5577 }
5578
Marcel Holtmann2faade52014-06-29 19:44:03 +02005579 if (cp->addr.type == BDADDR_LE_PUBLIC)
5580 addr_type = ADDR_LE_DEV_PUBLIC;
5581 else
5582 addr_type = ADDR_LE_DEV_RANDOM;
5583
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005584 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005585 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005586 else if (cp->action == 0x01)
5587 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005588 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005589 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005590
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005591 /* If the connection parameters don't exist for this device,
5592 * they will be created and configured with defaults.
5593 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005594 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005595 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005596 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005597 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005598 goto unlock;
5599 }
5600
Johan Hedberg66593582014-07-09 12:59:14 +03005601added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005602 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5603
Johan Hedberg5a154e62014-12-19 22:26:02 +02005604 err = hci_req_run(&req, add_device_complete);
5605 if (err < 0) {
5606 /* ENODATA means no HCI commands were needed (e.g. if
5607 * the adapter is powered off).
5608 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005609 if (err == -ENODATA)
5610 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005611 mgmt_pending_remove(cmd);
5612 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005613
5614unlock:
5615 hci_dev_unlock(hdev);
5616 return err;
5617}
5618
Marcel Holtmann8afef092014-06-29 22:28:34 +02005619static void device_removed(struct sock *sk, struct hci_dev *hdev,
5620 bdaddr_t *bdaddr, u8 type)
5621{
5622 struct mgmt_ev_device_removed ev;
5623
5624 bacpy(&ev.addr.bdaddr, bdaddr);
5625 ev.addr.type = type;
5626
5627 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5628}
5629
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005630static void remove_device_complete(struct hci_dev *hdev, u8 status)
5631{
5632 struct pending_cmd *cmd;
5633
5634 BT_DBG("status 0x%02x", status);
5635
5636 hci_dev_lock(hdev);
5637
5638 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5639 if (!cmd)
5640 goto unlock;
5641
5642 cmd->cmd_complete(cmd, mgmt_status(status));
5643 mgmt_pending_remove(cmd);
5644
5645unlock:
5646 hci_dev_unlock(hdev);
5647}
5648
Marcel Holtmann2faade52014-06-29 19:44:03 +02005649static int remove_device(struct sock *sk, struct hci_dev *hdev,
5650 void *data, u16 len)
5651{
5652 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005653 struct pending_cmd *cmd;
5654 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005655 int err;
5656
5657 BT_DBG("%s", hdev->name);
5658
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005659 hci_req_init(&req, hdev);
5660
Marcel Holtmann2faade52014-06-29 19:44:03 +02005661 hci_dev_lock(hdev);
5662
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005663 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5664 if (!cmd) {
5665 err = -ENOMEM;
5666 goto unlock;
5667 }
5668
5669 cmd->cmd_complete = addr_cmd_complete;
5670
Marcel Holtmann2faade52014-06-29 19:44:03 +02005671 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005672 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005673 u8 addr_type;
5674
Johan Hedberg66593582014-07-09 12:59:14 +03005675 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005676 err = cmd->cmd_complete(cmd,
5677 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005678 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005679 goto unlock;
5680 }
5681
Johan Hedberg66593582014-07-09 12:59:14 +03005682 if (cp->addr.type == BDADDR_BREDR) {
5683 err = hci_bdaddr_list_del(&hdev->whitelist,
5684 &cp->addr.bdaddr,
5685 cp->addr.type);
5686 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005687 err = cmd->cmd_complete(cmd,
5688 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005689 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005690 goto unlock;
5691 }
5692
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005693 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005694
Johan Hedberg66593582014-07-09 12:59:14 +03005695 device_removed(sk, hdev, &cp->addr.bdaddr,
5696 cp->addr.type);
5697 goto complete;
5698 }
5699
Marcel Holtmann2faade52014-06-29 19:44:03 +02005700 if (cp->addr.type == BDADDR_LE_PUBLIC)
5701 addr_type = ADDR_LE_DEV_PUBLIC;
5702 else
5703 addr_type = ADDR_LE_DEV_RANDOM;
5704
Johan Hedbergc71593d2014-07-02 17:37:28 +03005705 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5706 addr_type);
5707 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005708 err = cmd->cmd_complete(cmd,
5709 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005710 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005711 goto unlock;
5712 }
5713
5714 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005715 err = cmd->cmd_complete(cmd,
5716 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005717 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005718 goto unlock;
5719 }
5720
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005721 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005722 list_del(&params->list);
5723 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005724 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005725
5726 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005727 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005728 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005729 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005730
Marcel Holtmann2faade52014-06-29 19:44:03 +02005731 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005732 err = cmd->cmd_complete(cmd,
5733 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005734 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005735 goto unlock;
5736 }
5737
Johan Hedberg66593582014-07-09 12:59:14 +03005738 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5739 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5740 list_del(&b->list);
5741 kfree(b);
5742 }
5743
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005744 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005745
Johan Hedberg19de0822014-07-06 13:06:51 +03005746 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5747 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5748 continue;
5749 device_removed(sk, hdev, &p->addr, p->addr_type);
5750 list_del(&p->action);
5751 list_del(&p->list);
5752 kfree(p);
5753 }
5754
5755 BT_DBG("All LE connection parameters were removed");
5756
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005757 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005758 }
5759
Johan Hedberg66593582014-07-09 12:59:14 +03005760complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005761 err = hci_req_run(&req, remove_device_complete);
5762 if (err < 0) {
5763 /* ENODATA means no HCI commands were needed (e.g. if
5764 * the adapter is powered off).
5765 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005766 if (err == -ENODATA)
5767 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005768 mgmt_pending_remove(cmd);
5769 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005770
5771unlock:
5772 hci_dev_unlock(hdev);
5773 return err;
5774}
5775
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005776static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5777 u16 len)
5778{
5779 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005780 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5781 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005782 u16 param_count, expected_len;
5783 int i;
5784
5785 if (!lmp_le_capable(hdev))
5786 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5787 MGMT_STATUS_NOT_SUPPORTED);
5788
5789 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005790 if (param_count > max_param_count) {
5791 BT_ERR("load_conn_param: too big param_count value %u",
5792 param_count);
5793 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5794 MGMT_STATUS_INVALID_PARAMS);
5795 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005796
5797 expected_len = sizeof(*cp) + param_count *
5798 sizeof(struct mgmt_conn_param);
5799 if (expected_len != len) {
5800 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5801 expected_len, len);
5802 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5803 MGMT_STATUS_INVALID_PARAMS);
5804 }
5805
5806 BT_DBG("%s param_count %u", hdev->name, param_count);
5807
5808 hci_dev_lock(hdev);
5809
5810 hci_conn_params_clear_disabled(hdev);
5811
5812 for (i = 0; i < param_count; i++) {
5813 struct mgmt_conn_param *param = &cp->params[i];
5814 struct hci_conn_params *hci_param;
5815 u16 min, max, latency, timeout;
5816 u8 addr_type;
5817
5818 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5819 param->addr.type);
5820
5821 if (param->addr.type == BDADDR_LE_PUBLIC) {
5822 addr_type = ADDR_LE_DEV_PUBLIC;
5823 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5824 addr_type = ADDR_LE_DEV_RANDOM;
5825 } else {
5826 BT_ERR("Ignoring invalid connection parameters");
5827 continue;
5828 }
5829
5830 min = le16_to_cpu(param->min_interval);
5831 max = le16_to_cpu(param->max_interval);
5832 latency = le16_to_cpu(param->latency);
5833 timeout = le16_to_cpu(param->timeout);
5834
5835 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5836 min, max, latency, timeout);
5837
5838 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5839 BT_ERR("Ignoring invalid connection parameters");
5840 continue;
5841 }
5842
5843 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5844 addr_type);
5845 if (!hci_param) {
5846 BT_ERR("Failed to add connection parameters");
5847 continue;
5848 }
5849
5850 hci_param->conn_min_interval = min;
5851 hci_param->conn_max_interval = max;
5852 hci_param->conn_latency = latency;
5853 hci_param->supervision_timeout = timeout;
5854 }
5855
5856 hci_dev_unlock(hdev);
5857
5858 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5859}
5860
Marcel Holtmanndbece372014-07-04 18:11:55 +02005861static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5862 void *data, u16 len)
5863{
5864 struct mgmt_cp_set_external_config *cp = data;
5865 bool changed;
5866 int err;
5867
5868 BT_DBG("%s", hdev->name);
5869
5870 if (hdev_is_powered(hdev))
5871 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5872 MGMT_STATUS_REJECTED);
5873
5874 if (cp->config != 0x00 && cp->config != 0x01)
5875 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5876 MGMT_STATUS_INVALID_PARAMS);
5877
5878 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5879 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5880 MGMT_STATUS_NOT_SUPPORTED);
5881
5882 hci_dev_lock(hdev);
5883
5884 if (cp->config)
5885 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5886 &hdev->dev_flags);
5887 else
5888 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5889 &hdev->dev_flags);
5890
5891 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5892 if (err < 0)
5893 goto unlock;
5894
5895 if (!changed)
5896 goto unlock;
5897
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005898 err = new_options(hdev, sk);
5899
Marcel Holtmanndbece372014-07-04 18:11:55 +02005900 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5901 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005902
5903 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5904 set_bit(HCI_CONFIG, &hdev->dev_flags);
5905 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5906
5907 queue_work(hdev->req_workqueue, &hdev->power_on);
5908 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005909 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005910 mgmt_index_added(hdev);
5911 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005912 }
5913
5914unlock:
5915 hci_dev_unlock(hdev);
5916 return err;
5917}
5918
Marcel Holtmann9713c172014-07-06 12:11:15 +02005919static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5920 void *data, u16 len)
5921{
5922 struct mgmt_cp_set_public_address *cp = data;
5923 bool changed;
5924 int err;
5925
5926 BT_DBG("%s", hdev->name);
5927
5928 if (hdev_is_powered(hdev))
5929 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5930 MGMT_STATUS_REJECTED);
5931
5932 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5933 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5934 MGMT_STATUS_INVALID_PARAMS);
5935
5936 if (!hdev->set_bdaddr)
5937 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5938 MGMT_STATUS_NOT_SUPPORTED);
5939
5940 hci_dev_lock(hdev);
5941
5942 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5943 bacpy(&hdev->public_addr, &cp->bdaddr);
5944
5945 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5946 if (err < 0)
5947 goto unlock;
5948
5949 if (!changed)
5950 goto unlock;
5951
5952 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5953 err = new_options(hdev, sk);
5954
5955 if (is_configured(hdev)) {
5956 mgmt_index_removed(hdev);
5957
5958 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5959
5960 set_bit(HCI_CONFIG, &hdev->dev_flags);
5961 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5962
5963 queue_work(hdev->req_workqueue, &hdev->power_on);
5964 }
5965
5966unlock:
5967 hci_dev_unlock(hdev);
5968 return err;
5969}
5970
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005971static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005972 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5973 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005974 bool var_len;
5975 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005976} mgmt_handlers[] = {
5977 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005978 { read_version, false, MGMT_READ_VERSION_SIZE },
5979 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5980 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5981 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5982 { set_powered, false, MGMT_SETTING_SIZE },
5983 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5984 { set_connectable, false, MGMT_SETTING_SIZE },
5985 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005986 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005987 { set_link_security, false, MGMT_SETTING_SIZE },
5988 { set_ssp, false, MGMT_SETTING_SIZE },
5989 { set_hs, false, MGMT_SETTING_SIZE },
5990 { set_le, false, MGMT_SETTING_SIZE },
5991 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5992 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5993 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5994 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5995 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5996 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5997 { disconnect, false, MGMT_DISCONNECT_SIZE },
5998 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5999 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
6000 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6001 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6002 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6003 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6004 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6005 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6006 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6007 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6008 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6009 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006010 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006011 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6012 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6013 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6014 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6015 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6016 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006017 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006018 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006019 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006020 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006021 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006022 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006023 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006024 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006025 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006026 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006027 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006028 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6029 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006030 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6031 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006032 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006033 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006034 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006035 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006036};
6037
Johan Hedberg03811012010-12-08 00:21:06 +02006038int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6039{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006040 void *buf;
6041 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006042 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006043 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006044 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006045 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006046 int err;
6047
6048 BT_DBG("got %zu bytes", msglen);
6049
6050 if (msglen < sizeof(*hdr))
6051 return -EINVAL;
6052
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006053 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006054 if (!buf)
6055 return -ENOMEM;
6056
Al Viro6ce8e9c2014-04-06 21:25:44 -04006057 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006058 err = -EFAULT;
6059 goto done;
6060 }
6061
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006062 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006063 opcode = __le16_to_cpu(hdr->opcode);
6064 index = __le16_to_cpu(hdr->index);
6065 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006066
6067 if (len != msglen - sizeof(*hdr)) {
6068 err = -EINVAL;
6069 goto done;
6070 }
6071
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006072 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006073 hdev = hci_dev_get(index);
6074 if (!hdev) {
6075 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006076 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006077 goto done;
6078 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006079
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006080 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006081 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006082 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006083 err = cmd_status(sk, index, opcode,
6084 MGMT_STATUS_INVALID_INDEX);
6085 goto done;
6086 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006087
6088 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006089 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006090 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6091 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006092 err = cmd_status(sk, index, opcode,
6093 MGMT_STATUS_INVALID_INDEX);
6094 goto done;
6095 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006096 }
6097
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006098 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006099 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006100 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006101 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006102 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006103 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006104 }
6105
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006106 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6107 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6108 err = cmd_status(sk, index, opcode,
6109 MGMT_STATUS_INVALID_INDEX);
6110 goto done;
6111 }
6112
6113 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6114 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006115 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006116 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006117 goto done;
6118 }
6119
Johan Hedbergbe22b542012-03-01 22:24:41 +02006120 handler = &mgmt_handlers[opcode];
6121
6122 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006123 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006124 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006125 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006126 goto done;
6127 }
6128
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006129 if (hdev)
6130 mgmt_init_hdev(sk, hdev);
6131
6132 cp = buf + sizeof(*hdr);
6133
Johan Hedbergbe22b542012-03-01 22:24:41 +02006134 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006135 if (err < 0)
6136 goto done;
6137
Johan Hedberg03811012010-12-08 00:21:06 +02006138 err = msglen;
6139
6140done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006141 if (hdev)
6142 hci_dev_put(hdev);
6143
Johan Hedberg03811012010-12-08 00:21:06 +02006144 kfree(buf);
6145 return err;
6146}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006147
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006148void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006149{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006150 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006151 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006152
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006153 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6154 return;
6155
6156 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6157 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6158 else
6159 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006160}
6161
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006162void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006163{
Johan Hedberg5f159032012-03-02 03:13:19 +02006164 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006165
Marcel Holtmann1514b892013-10-06 08:25:01 -07006166 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006167 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006168
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006169 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6170 return;
6171
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006172 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006173
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02006174 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6175 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6176 else
6177 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006178}
6179
Andre Guedes6046dc32014-02-26 20:21:51 -03006180/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006181static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006182{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006183 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006184 struct hci_conn_params *p;
6185
6186 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006187 /* Needed for AUTO_OFF case where might not "really"
6188 * have been powered off.
6189 */
6190 list_del_init(&p->action);
6191
6192 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006193 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006194 case HCI_AUTO_CONN_ALWAYS:
6195 list_add(&p->action, &hdev->pend_le_conns);
6196 break;
6197 case HCI_AUTO_CONN_REPORT:
6198 list_add(&p->action, &hdev->pend_le_reports);
6199 break;
6200 default:
6201 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006202 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006203 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006204
Johan Hedberg2cf22212014-12-19 22:26:00 +02006205 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006206}
6207
Johan Hedberg229ab392013-03-15 17:06:53 -05006208static void powered_complete(struct hci_dev *hdev, u8 status)
6209{
6210 struct cmd_lookup match = { NULL, hdev };
6211
6212 BT_DBG("status 0x%02x", status);
6213
6214 hci_dev_lock(hdev);
6215
6216 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6217
6218 new_settings(hdev, match.sk);
6219
6220 hci_dev_unlock(hdev);
6221
6222 if (match.sk)
6223 sock_put(match.sk);
6224}
6225
Johan Hedberg70da6242013-03-15 17:06:51 -05006226static int powered_update_hci(struct hci_dev *hdev)
6227{
Johan Hedberg890ea892013-03-15 17:06:52 -05006228 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006229 u8 link_sec;
6230
Johan Hedberg890ea892013-03-15 17:06:52 -05006231 hci_req_init(&req, hdev);
6232
Johan Hedberg70da6242013-03-15 17:06:51 -05006233 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6234 !lmp_host_ssp_capable(hdev)) {
6235 u8 ssp = 1;
6236
Johan Hedberg890ea892013-03-15 17:06:52 -05006237 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006238 }
6239
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006240 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6241 u8 sc = 0x01;
6242 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
6243 }
6244
Johan Hedbergc73eee92013-04-19 18:35:21 +03006245 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6246 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006247 struct hci_cp_write_le_host_supported cp;
6248
Marcel Holtmann32226e42014-07-24 20:04:16 +02006249 cp.le = 0x01;
6250 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006251
6252 /* Check first if we already have the right
6253 * host state (host features set)
6254 */
6255 if (cp.le != lmp_host_le_capable(hdev) ||
6256 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006257 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6258 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006259 }
6260
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006261 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006262 /* Make sure the controller has a good default for
6263 * advertising data. This also applies to the case
6264 * where BR/EDR was toggled during the AUTO_OFF phase.
6265 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006266 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006267 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006268 update_scan_rsp_data(&req);
6269 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006270
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006271 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6272 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006273
6274 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006275 }
6276
Johan Hedberg70da6242013-03-15 17:06:51 -05006277 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6278 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006279 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6280 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006281
6282 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006283 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006284 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006285 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006286 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006287 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006288 }
6289
Johan Hedberg229ab392013-03-15 17:06:53 -05006290 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006291}
6292
Johan Hedberg744cf192011-11-08 20:40:14 +02006293int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006294{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006295 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006296 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006297 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006298
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006299 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6300 return 0;
6301
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006302 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006303 if (powered_update_hci(hdev) == 0)
6304 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006305
Johan Hedberg229ab392013-03-15 17:06:53 -05006306 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6307 &match);
6308 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006309 }
6310
Johan Hedberg229ab392013-03-15 17:06:53 -05006311 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006312
6313 /* If the power off is because of hdev unregistration let
6314 * use the appropriate INVALID_INDEX status. Otherwise use
6315 * NOT_POWERED. We cover both scenarios here since later in
6316 * mgmt_index_removed() any hci_conn callbacks will have already
6317 * been triggered, potentially causing misleading DISCONNECTED
6318 * status responses.
6319 */
6320 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6321 status = MGMT_STATUS_INVALID_INDEX;
6322 else
6323 status = MGMT_STATUS_NOT_POWERED;
6324
6325 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006326
6327 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6328 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6329 zero_cod, sizeof(zero_cod), NULL);
6330
6331new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006332 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006333
6334 if (match.sk)
6335 sock_put(match.sk);
6336
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006337 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006338}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006339
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006340void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006341{
6342 struct pending_cmd *cmd;
6343 u8 status;
6344
6345 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6346 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006347 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006348
6349 if (err == -ERFKILL)
6350 status = MGMT_STATUS_RFKILLED;
6351 else
6352 status = MGMT_STATUS_FAILED;
6353
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006354 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006355
6356 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006357}
6358
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006359void mgmt_discoverable_timeout(struct hci_dev *hdev)
6360{
6361 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006362
6363 hci_dev_lock(hdev);
6364
6365 /* When discoverable timeout triggers, then just make sure
6366 * the limited discoverable flag is cleared. Even in the case
6367 * of a timeout triggered from general discoverable, it is
6368 * safe to unconditionally clear the flag.
6369 */
6370 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006371 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006372
6373 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006374 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6375 u8 scan = SCAN_PAGE;
6376 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6377 sizeof(scan), &scan);
6378 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006379 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006380 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006381 hci_req_run(&req, NULL);
6382
6383 hdev->discov_timeout = 0;
6384
Johan Hedberg9a43e252013-10-20 19:00:07 +03006385 new_settings(hdev, NULL);
6386
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006387 hci_dev_unlock(hdev);
6388}
6389
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006390void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6391 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006392{
Johan Hedberg86742e12011-11-07 23:13:38 +02006393 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006394
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006395 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006396
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006397 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006398 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006399 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006400 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006401 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006402 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006403
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006404 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006405}
Johan Hedbergf7520542011-01-20 12:34:39 +02006406
Johan Hedbergd7b25452014-05-23 13:19:53 +03006407static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6408{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006409 switch (ltk->type) {
6410 case SMP_LTK:
6411 case SMP_LTK_SLAVE:
6412 if (ltk->authenticated)
6413 return MGMT_LTK_AUTHENTICATED;
6414 return MGMT_LTK_UNAUTHENTICATED;
6415 case SMP_LTK_P256:
6416 if (ltk->authenticated)
6417 return MGMT_LTK_P256_AUTH;
6418 return MGMT_LTK_P256_UNAUTH;
6419 case SMP_LTK_P256_DEBUG:
6420 return MGMT_LTK_P256_DEBUG;
6421 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006422
6423 return MGMT_LTK_UNAUTHENTICATED;
6424}
6425
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006426void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006427{
6428 struct mgmt_ev_new_long_term_key ev;
6429
6430 memset(&ev, 0, sizeof(ev));
6431
Marcel Holtmann5192d302014-02-19 17:11:58 -08006432 /* Devices using resolvable or non-resolvable random addresses
6433 * without providing an indentity resolving key don't require
6434 * to store long term keys. Their addresses will change the
6435 * next time around.
6436 *
6437 * Only when a remote device provides an identity address
6438 * make sure the long term key is stored. If the remote
6439 * identity is known, the long term keys are internally
6440 * mapped to the identity address. So allow static random
6441 * and public addresses here.
6442 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006443 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6444 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6445 ev.store_hint = 0x00;
6446 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006447 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006448
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006449 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006450 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006451 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006452 ev.key.enc_size = key->enc_size;
6453 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006454 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006455
Johan Hedberg2ceba532014-06-16 19:25:16 +03006456 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006457 ev.key.master = 1;
6458
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006459 memcpy(ev.key.val, key->val, sizeof(key->val));
6460
Marcel Holtmann083368f2013-10-15 14:26:29 -07006461 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006462}
6463
Johan Hedberg95fbac82014-02-19 15:18:31 +02006464void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6465{
6466 struct mgmt_ev_new_irk ev;
6467
6468 memset(&ev, 0, sizeof(ev));
6469
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006470 /* For identity resolving keys from devices that are already
6471 * using a public address or static random address, do not
6472 * ask for storing this key. The identity resolving key really
6473 * is only mandatory for devices using resovlable random
6474 * addresses.
6475 *
6476 * Storing all identity resolving keys has the downside that
6477 * they will be also loaded on next boot of they system. More
6478 * identity resolving keys, means more time during scanning is
6479 * needed to actually resolve these addresses.
6480 */
6481 if (bacmp(&irk->rpa, BDADDR_ANY))
6482 ev.store_hint = 0x01;
6483 else
6484 ev.store_hint = 0x00;
6485
Johan Hedberg95fbac82014-02-19 15:18:31 +02006486 bacpy(&ev.rpa, &irk->rpa);
6487 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6488 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6489 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6490
6491 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6492}
6493
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006494void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6495 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006496{
6497 struct mgmt_ev_new_csrk ev;
6498
6499 memset(&ev, 0, sizeof(ev));
6500
6501 /* Devices using resolvable or non-resolvable random addresses
6502 * without providing an indentity resolving key don't require
6503 * to store signature resolving keys. Their addresses will change
6504 * the next time around.
6505 *
6506 * Only when a remote device provides an identity address
6507 * make sure the signature resolving key is stored. So allow
6508 * static random and public addresses here.
6509 */
6510 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6511 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6512 ev.store_hint = 0x00;
6513 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006514 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006515
6516 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6517 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6518 ev.key.master = csrk->master;
6519 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6520
6521 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6522}
6523
Andre Guedesffb5a8272014-07-01 18:10:11 -03006524void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006525 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6526 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006527{
6528 struct mgmt_ev_new_conn_param ev;
6529
Johan Hedbergc103aea2014-07-02 17:37:34 +03006530 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6531 return;
6532
Andre Guedesffb5a8272014-07-01 18:10:11 -03006533 memset(&ev, 0, sizeof(ev));
6534 bacpy(&ev.addr.bdaddr, bdaddr);
6535 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006536 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006537 ev.min_interval = cpu_to_le16(min_interval);
6538 ev.max_interval = cpu_to_le16(max_interval);
6539 ev.latency = cpu_to_le16(latency);
6540 ev.timeout = cpu_to_le16(timeout);
6541
6542 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6543}
6544
Marcel Holtmann94933992013-10-15 10:26:39 -07006545static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6546 u8 data_len)
6547{
6548 eir[eir_len++] = sizeof(type) + data_len;
6549 eir[eir_len++] = type;
6550 memcpy(&eir[eir_len], data, data_len);
6551 eir_len += data_len;
6552
6553 return eir_len;
6554}
6555
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006556void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6557 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006558{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006559 char buf[512];
6560 struct mgmt_ev_device_connected *ev = (void *) buf;
6561 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006562
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006563 bacpy(&ev->addr.bdaddr, &conn->dst);
6564 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006565
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006566 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006567
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006568 /* We must ensure that the EIR Data fields are ordered and
6569 * unique. Keep it simple for now and avoid the problem by not
6570 * adding any BR/EDR data to the LE adv.
6571 */
6572 if (conn->le_adv_data_len > 0) {
6573 memcpy(&ev->eir[eir_len],
6574 conn->le_adv_data, conn->le_adv_data_len);
6575 eir_len = conn->le_adv_data_len;
6576 } else {
6577 if (name_len > 0)
6578 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6579 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006580
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006581 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006582 eir_len = eir_append_data(ev->eir, eir_len,
6583 EIR_CLASS_OF_DEV,
6584 conn->dev_class, 3);
6585 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006586
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006587 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006588
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006589 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6590 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006591}
6592
Johan Hedberg8962ee72011-01-20 12:40:27 +02006593static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6594{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006595 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006596
Johan Hedbergf5818c22014-12-05 13:36:02 +02006597 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006598
6599 *sk = cmd->sk;
6600 sock_hold(*sk);
6601
Johan Hedberga664b5b2011-02-19 12:06:02 -03006602 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006603}
6604
Johan Hedberg124f6e32012-02-09 13:50:12 +02006605static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006606{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006607 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006608 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006609
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006610 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6611
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006612 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006613 mgmt_pending_remove(cmd);
6614}
6615
Johan Hedberg84c61d92014-08-01 11:13:30 +03006616bool mgmt_powering_down(struct hci_dev *hdev)
6617{
6618 struct pending_cmd *cmd;
6619 struct mgmt_mode *cp;
6620
6621 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6622 if (!cmd)
6623 return false;
6624
6625 cp = cmd->param;
6626 if (!cp->val)
6627 return true;
6628
6629 return false;
6630}
6631
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006632void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006633 u8 link_type, u8 addr_type, u8 reason,
6634 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006635{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006636 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006637 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006638
Johan Hedberg84c61d92014-08-01 11:13:30 +03006639 /* The connection is still in hci_conn_hash so test for 1
6640 * instead of 0 to know if this is the last one.
6641 */
6642 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6643 cancel_delayed_work(&hdev->power_off);
6644 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006645 }
6646
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006647 if (!mgmt_connected)
6648 return;
6649
Andre Guedes57eb7762013-10-30 19:01:41 -03006650 if (link_type != ACL_LINK && link_type != LE_LINK)
6651 return;
6652
Johan Hedberg744cf192011-11-08 20:40:14 +02006653 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006654
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006655 bacpy(&ev.addr.bdaddr, bdaddr);
6656 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6657 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006658
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006659 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006660
6661 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006662 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006663
Johan Hedberg124f6e32012-02-09 13:50:12 +02006664 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006665 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006666}
6667
Marcel Holtmann78929242013-10-06 23:55:47 -07006668void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6669 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006670{
Andre Guedes3655bba2013-10-30 19:01:40 -03006671 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6672 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006673 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006674
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006675 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6676 hdev);
6677
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006678 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006679 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006680 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006681
Andre Guedes3655bba2013-10-30 19:01:40 -03006682 cp = cmd->param;
6683
6684 if (bacmp(bdaddr, &cp->addr.bdaddr))
6685 return;
6686
6687 if (cp->addr.type != bdaddr_type)
6688 return;
6689
Johan Hedbergf5818c22014-12-05 13:36:02 +02006690 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006691 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006692}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006693
Marcel Holtmann445608d2013-10-06 23:55:48 -07006694void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6695 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006696{
6697 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006698
Johan Hedberg84c61d92014-08-01 11:13:30 +03006699 /* The connection is still in hci_conn_hash so test for 1
6700 * instead of 0 to know if this is the last one.
6701 */
6702 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6703 cancel_delayed_work(&hdev->power_off);
6704 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006705 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006706
Johan Hedberg4c659c32011-11-07 23:13:39 +02006707 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006708 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006709 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006710
Marcel Holtmann445608d2013-10-06 23:55:48 -07006711 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006712}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006713
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006714void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006715{
6716 struct mgmt_ev_pin_code_request ev;
6717
Johan Hedbergd8457692012-02-17 14:24:57 +02006718 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006719 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006720 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006721
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006722 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006723}
6724
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006725void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6726 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006727{
6728 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006729
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006730 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006731 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006732 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006733
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006734 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006735 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006736}
6737
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006738void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6739 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006740{
6741 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006742
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006743 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006744 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006745 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006746
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006747 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006748 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006749}
Johan Hedberga5c29682011-02-19 12:05:57 -03006750
Johan Hedberg744cf192011-11-08 20:40:14 +02006751int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006752 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006753 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006754{
6755 struct mgmt_ev_user_confirm_request ev;
6756
Johan Hedberg744cf192011-11-08 20:40:14 +02006757 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006758
Johan Hedberg272d90d2012-02-09 15:26:12 +02006759 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006760 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006761 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006762 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006763
Johan Hedberg744cf192011-11-08 20:40:14 +02006764 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006765 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006766}
6767
Johan Hedberg272d90d2012-02-09 15:26:12 +02006768int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006769 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006770{
6771 struct mgmt_ev_user_passkey_request ev;
6772
6773 BT_DBG("%s", hdev->name);
6774
Johan Hedberg272d90d2012-02-09 15:26:12 +02006775 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006776 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006777
6778 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006779 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006780}
6781
Brian Gix0df4c182011-11-16 13:53:13 -08006782static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006783 u8 link_type, u8 addr_type, u8 status,
6784 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006785{
6786 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006787
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006788 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006789 if (!cmd)
6790 return -ENOENT;
6791
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006792 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006793 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006794
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006795 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006796}
6797
Johan Hedberg744cf192011-11-08 20:40:14 +02006798int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006799 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006800{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006801 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006802 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006803}
6804
Johan Hedberg272d90d2012-02-09 15:26:12 +02006805int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006806 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006807{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006808 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006809 status,
6810 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006811}
Johan Hedberg2a611692011-02-19 12:06:00 -03006812
Brian Gix604086b2011-11-23 08:28:33 -08006813int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006814 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006815{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006816 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006817 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006818}
6819
Johan Hedberg272d90d2012-02-09 15:26:12 +02006820int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006821 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006822{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006823 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006824 status,
6825 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006826}
6827
Johan Hedberg92a25252012-09-06 18:39:26 +03006828int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6829 u8 link_type, u8 addr_type, u32 passkey,
6830 u8 entered)
6831{
6832 struct mgmt_ev_passkey_notify ev;
6833
6834 BT_DBG("%s", hdev->name);
6835
6836 bacpy(&ev.addr.bdaddr, bdaddr);
6837 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6838 ev.passkey = __cpu_to_le32(passkey);
6839 ev.entered = entered;
6840
6841 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6842}
6843
Johan Hedberge1e930f2014-09-08 17:09:49 -07006844void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006845{
6846 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006847 struct pending_cmd *cmd;
6848 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006849
Johan Hedberge1e930f2014-09-08 17:09:49 -07006850 bacpy(&ev.addr.bdaddr, &conn->dst);
6851 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6852 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006853
Johan Hedberge1e930f2014-09-08 17:09:49 -07006854 cmd = find_pairing(conn);
6855
6856 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6857 cmd ? cmd->sk : NULL);
6858
Johan Hedberga511b352014-12-11 21:45:45 +02006859 if (cmd) {
6860 cmd->cmd_complete(cmd, status);
6861 mgmt_pending_remove(cmd);
6862 }
Johan Hedberg2a611692011-02-19 12:06:00 -03006863}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006864
Marcel Holtmann464996a2013-10-15 14:26:24 -07006865void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006866{
6867 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006868 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006869
6870 if (status) {
6871 u8 mgmt_err = mgmt_status(status);
6872 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006873 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006874 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006875 }
6876
Marcel Holtmann464996a2013-10-15 14:26:24 -07006877 if (test_bit(HCI_AUTH, &hdev->flags))
6878 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6879 &hdev->dev_flags);
6880 else
6881 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6882 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006883
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006884 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006885 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006886
Johan Hedberg47990ea2012-02-22 11:58:37 +02006887 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006888 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006889
6890 if (match.sk)
6891 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006892}
6893
Johan Hedberg890ea892013-03-15 17:06:52 -05006894static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006895{
Johan Hedberg890ea892013-03-15 17:06:52 -05006896 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006897 struct hci_cp_write_eir cp;
6898
Johan Hedberg976eb202012-10-24 21:12:01 +03006899 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006900 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006901
Johan Hedbergc80da272012-02-22 15:38:48 +02006902 memset(hdev->eir, 0, sizeof(hdev->eir));
6903
Johan Hedbergcacaf522012-02-21 00:52:42 +02006904 memset(&cp, 0, sizeof(cp));
6905
Johan Hedberg890ea892013-03-15 17:06:52 -05006906 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006907}
6908
Marcel Holtmann3e248562013-10-15 14:26:25 -07006909void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006910{
6911 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006912 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006913 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006914
6915 if (status) {
6916 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006917
6918 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006919 &hdev->dev_flags)) {
6920 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006921 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006922 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006923
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006924 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6925 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006926 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006927 }
6928
6929 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006930 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006931 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006932 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6933 if (!changed)
6934 changed = test_and_clear_bit(HCI_HS_ENABLED,
6935 &hdev->dev_flags);
6936 else
6937 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006938 }
6939
6940 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6941
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006942 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006943 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006944
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006945 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006946 sock_put(match.sk);
6947
Johan Hedberg890ea892013-03-15 17:06:52 -05006948 hci_req_init(&req, hdev);
6949
Johan Hedberg37699722014-06-24 14:00:27 +03006950 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6951 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6952 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6953 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006954 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006955 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006956 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006957 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006958
6959 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006960}
6961
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006962void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6963{
6964 struct cmd_lookup match = { NULL, hdev };
6965 bool changed = false;
6966
6967 if (status) {
6968 u8 mgmt_err = mgmt_status(status);
6969
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006970 if (enable) {
6971 if (test_and_clear_bit(HCI_SC_ENABLED,
6972 &hdev->dev_flags))
6973 new_settings(hdev, NULL);
6974 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6975 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006976
6977 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6978 cmd_status_rsp, &mgmt_err);
6979 return;
6980 }
6981
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006982 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006983 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006984 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006985 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006986 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6987 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006988
6989 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6990 settings_rsp, &match);
6991
6992 if (changed)
6993 new_settings(hdev, match.sk);
6994
6995 if (match.sk)
6996 sock_put(match.sk);
6997}
6998
Johan Hedberg92da6092013-03-15 17:06:55 -05006999static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007000{
7001 struct cmd_lookup *match = data;
7002
Johan Hedberg90e70452012-02-23 23:09:40 +02007003 if (match->sk == NULL) {
7004 match->sk = cmd->sk;
7005 sock_hold(match->sk);
7006 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007007}
7008
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007009void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7010 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007011{
Johan Hedberg90e70452012-02-23 23:09:40 +02007012 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007013
Johan Hedberg92da6092013-03-15 17:06:55 -05007014 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7015 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7016 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007017
7018 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007019 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7020 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007021
7022 if (match.sk)
7023 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007024}
7025
Marcel Holtmann7667da32013-10-15 14:26:27 -07007026void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007027{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007028 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007029 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007030
Johan Hedberg13928972013-03-15 17:07:00 -05007031 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007032 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007033
7034 memset(&ev, 0, sizeof(ev));
7035 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007036 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007037
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007038 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007039 if (!cmd) {
7040 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007041
Johan Hedberg13928972013-03-15 17:07:00 -05007042 /* If this is a HCI command related to powering on the
7043 * HCI dev don't send any mgmt signals.
7044 */
7045 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007046 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007047 }
7048
Marcel Holtmann7667da32013-10-15 14:26:27 -07007049 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7050 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007051}
Szymon Jancc35938b2011-03-22 13:12:21 +01007052
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007053void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007054 u8 *rand192, u8 *hash256, u8 *rand256,
7055 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007056{
7057 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007058
Johan Hedberg744cf192011-11-08 20:40:14 +02007059 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007060
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007061 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007062 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007063 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007064
7065 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007066 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7067 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007068 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03007069 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007070 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01007071
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007072 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02007073 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01007074
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007075 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007076 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007077
7078 cmd_complete(cmd->sk, hdev->id,
7079 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7080 &rp, sizeof(rp));
7081 } else {
7082 struct mgmt_rp_read_local_oob_data rp;
7083
7084 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02007085 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007086
7087 cmd_complete(cmd->sk, hdev->id,
7088 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7089 &rp, sizeof(rp));
7090 }
Szymon Jancc35938b2011-03-22 13:12:21 +01007091 }
7092
7093 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007094}
Johan Hedberge17acd42011-03-30 23:57:16 +03007095
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007096static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7097{
7098 int i;
7099
7100 for (i = 0; i < uuid_count; i++) {
7101 if (!memcmp(uuid, uuids[i], 16))
7102 return true;
7103 }
7104
7105 return false;
7106}
7107
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007108static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7109{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007110 u16 parsed = 0;
7111
7112 while (parsed < eir_len) {
7113 u8 field_len = eir[0];
7114 u8 uuid[16];
7115 int i;
7116
7117 if (field_len == 0)
7118 break;
7119
7120 if (eir_len - parsed < field_len + 1)
7121 break;
7122
7123 switch (eir[1]) {
7124 case EIR_UUID16_ALL:
7125 case EIR_UUID16_SOME:
7126 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007127 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007128 uuid[13] = eir[i + 3];
7129 uuid[12] = eir[i + 2];
7130 if (has_uuid(uuid, uuid_count, uuids))
7131 return true;
7132 }
7133 break;
7134 case EIR_UUID32_ALL:
7135 case EIR_UUID32_SOME:
7136 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007137 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007138 uuid[15] = eir[i + 5];
7139 uuid[14] = eir[i + 4];
7140 uuid[13] = eir[i + 3];
7141 uuid[12] = eir[i + 2];
7142 if (has_uuid(uuid, uuid_count, uuids))
7143 return true;
7144 }
7145 break;
7146 case EIR_UUID128_ALL:
7147 case EIR_UUID128_SOME:
7148 for (i = 0; i + 17 <= field_len; i += 16) {
7149 memcpy(uuid, eir + i + 2, 16);
7150 if (has_uuid(uuid, uuid_count, uuids))
7151 return true;
7152 }
7153 break;
7154 }
7155
7156 parsed += field_len + 1;
7157 eir += field_len + 1;
7158 }
7159
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007160 return false;
7161}
7162
Marcel Holtmann901801b2013-10-06 23:55:51 -07007163void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007164 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7165 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007166{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007167 char buf[512];
7168 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007169 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007170 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007171
Johan Hedberg75ce2082014-07-02 22:42:01 +03007172 /* Don't send events for a non-kernel initiated discovery. With
7173 * LE one exception is if we have pend_le_reports > 0 in which
7174 * case we're doing passive scanning and want these events.
7175 */
7176 if (!hci_discovery_active(hdev)) {
7177 if (link_type == ACL_LINK)
7178 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007179 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007180 return;
7181 }
Andre Guedes12602d02013-04-30 15:29:40 -03007182
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007183 /* When using service discovery with a RSSI threshold, then check
7184 * if such a RSSI threshold is specified. If a RSSI threshold has
7185 * been specified, then all results with a RSSI smaller than the
7186 * RSSI threshold will be dropped.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007187 *
7188 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7189 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007190 */
7191 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Marcel Holtmannefb25132014-12-05 13:03:34 +01007192 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007193 return;
7194
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007195 /* Make sure that the buffer is big enough. The 5 extra bytes
7196 * are for the potential CoD field.
7197 */
7198 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007199 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007200
Johan Hedberg1dc06092012-01-15 21:01:23 +02007201 memset(buf, 0, sizeof(buf));
7202
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007203 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7204 * RSSI value was reported as 0 when not available. This behavior
7205 * is kept when using device discovery. This is required for full
7206 * backwards compatibility with the API.
7207 *
7208 * However when using service discovery, the value 127 will be
7209 * returned when the RSSI is not available.
7210 */
7211 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007212 rssi = 0;
7213
Johan Hedberg841c5642014-07-07 12:45:54 +03007214 bacpy(&ev->addr.bdaddr, bdaddr);
7215 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007216 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007217 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007218
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007219 if (eir_len > 0) {
7220 /* When using service discovery and a list of UUID is
7221 * provided, results with no matching UUID should be
7222 * dropped. In case there is a match the result is
7223 * kept and checking possible scan response data
7224 * will be skipped.
7225 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007226 if (hdev->discovery.uuid_count > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007227 match = eir_has_uuids(eir, eir_len,
7228 hdev->discovery.uuid_count,
7229 hdev->discovery.uuids);
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007230 else
7231 match = true;
7232
7233 if (!match && !scan_rsp_len)
7234 return;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007235
7236 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007237 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007238 } else {
7239 /* When using service discovery and a list of UUID is
7240 * provided, results with empty EIR or advertising data
7241 * should be dropped since they do not match any UUID.
7242 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007243 if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007244 return;
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007245
7246 match = false;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007247 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007248
Johan Hedberg1dc06092012-01-15 21:01:23 +02007249 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7250 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007251 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007252
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007253 if (scan_rsp_len > 0) {
7254 /* When using service discovery and a list of UUID is
7255 * provided, results with no matching UUID should be
7256 * dropped if there is no previous match from the
7257 * advertising data.
7258 */
7259 if (hdev->discovery.uuid_count > 0) {
7260 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7261 hdev->discovery.uuid_count,
7262 hdev->discovery.uuids))
7263 return;
7264 }
7265
7266 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007267 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007268 } else {
7269 /* When using service discovery and a list of UUID is
7270 * provided, results with empty scan response and no
7271 * previous matched advertising data should be dropped.
7272 */
7273 if (hdev->discovery.uuid_count > 0 && !match)
7274 return;
7275 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007276
7277 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7278 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007279
Marcel Holtmann901801b2013-10-06 23:55:51 -07007280 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007281}
Johan Hedberga88a9652011-03-30 13:18:12 +03007282
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007283void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7284 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007285{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007286 struct mgmt_ev_device_found *ev;
7287 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7288 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007289
Johan Hedbergb644ba32012-01-17 21:48:47 +02007290 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007291
Johan Hedbergb644ba32012-01-17 21:48:47 +02007292 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007293
Johan Hedbergb644ba32012-01-17 21:48:47 +02007294 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007295 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007296 ev->rssi = rssi;
7297
7298 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007299 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007300
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007301 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007302
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007303 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007304}
Johan Hedberg314b2382011-04-27 10:29:57 -04007305
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007306void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007307{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007308 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007309
Andre Guedes343fb142011-11-22 17:14:19 -03007310 BT_DBG("%s discovering %u", hdev->name, discovering);
7311
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007312 memset(&ev, 0, sizeof(ev));
7313 ev.type = hdev->discovery.type;
7314 ev.discovering = discovering;
7315
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007316 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007317}
Antti Julku5e762442011-08-25 16:48:02 +03007318
Marcel Holtmann5976e602013-10-06 04:08:14 -07007319static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7320{
7321 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007322}
7323
7324void mgmt_reenable_advertising(struct hci_dev *hdev)
7325{
7326 struct hci_request req;
7327
Marcel Holtmann5976e602013-10-06 04:08:14 -07007328 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7329 return;
7330
7331 hci_req_init(&req, hdev);
7332 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007333 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007334}