blob: 41e30055bae879c148ff8488622c5abf30c8d03c [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
Marcel Holtmann1904a852015-01-11 13:50:44 -08001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001255{
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
Marcel Holtmann1904a852015-01-11 13:50:44 -08001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1522 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001523{
1524 struct pending_cmd *cmd;
1525 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001526 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001527 bool changed;
1528
1529 BT_DBG("status 0x%02x", status);
1530
1531 hci_dev_lock(hdev);
1532
1533 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1534 if (!cmd)
1535 goto unlock;
1536
1537 if (status) {
1538 u8 mgmt_err = mgmt_status(status);
1539 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001540 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001541 goto remove_cmd;
1542 }
1543
1544 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001545 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001546 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1547 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001548
1549 if (hdev->discov_timeout > 0) {
1550 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1551 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1552 to);
1553 }
1554 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001555 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1556 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001557 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001558
1559 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1560
1561 if (changed)
1562 new_settings(hdev, cmd->sk);
1563
Marcel Holtmann970ba522013-10-15 06:33:57 -07001564 /* When the discoverable mode gets changed, make sure
1565 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001566 * bit correctly set. Also update page scan based on whitelist
1567 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001568 */
1569 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001570 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001571 update_class(&req);
1572 hci_req_run(&req, NULL);
1573
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001574remove_cmd:
1575 mgmt_pending_remove(cmd);
1576
1577unlock:
1578 hci_dev_unlock(hdev);
1579}
1580
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001581static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001582 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001583{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001584 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001585 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001586 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001587 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001588 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001589 int err;
1590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001591 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001592
Johan Hedberg9a43e252013-10-20 19:00:07 +03001593 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1594 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001595 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001596 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001597
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001598 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001599 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1600 MGMT_STATUS_INVALID_PARAMS);
1601
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001602 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001603
1604 /* Disabling discoverable requires that no timeout is set,
1605 * and enabling limited discoverable requires a timeout.
1606 */
1607 if ((cp->val == 0x00 && timeout > 0) ||
1608 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001609 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001610 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001611
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001612 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001613
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001614 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001615 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001616 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001617 goto failed;
1618 }
1619
1620 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001621 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001622 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001623 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001624 goto failed;
1625 }
1626
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001627 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001628 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001629 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001630 goto failed;
1631 }
1632
1633 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001634 bool changed = false;
1635
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001636 /* Setting limited discoverable when powered off is
1637 * not a valid operation since it requires a timeout
1638 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1639 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001640 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1641 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1642 changed = true;
1643 }
1644
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001645 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001646 if (err < 0)
1647 goto failed;
1648
1649 if (changed)
1650 err = new_settings(hdev, sk);
1651
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001652 goto failed;
1653 }
1654
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001655 /* If the current mode is the same, then just update the timeout
1656 * value with the new value. And if only the timeout gets updated,
1657 * then no need for any HCI transactions.
1658 */
1659 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1660 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1661 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001662 cancel_delayed_work(&hdev->discov_off);
1663 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001664
Marcel Holtmann36261542013-10-15 08:28:51 -07001665 if (cp->val && hdev->discov_timeout > 0) {
1666 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001667 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001668 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001669 }
1670
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001671 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001672 goto failed;
1673 }
1674
1675 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1676 if (!cmd) {
1677 err = -ENOMEM;
1678 goto failed;
1679 }
1680
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001681 /* Cancel any potential discoverable timeout that might be
1682 * still active and store new timeout value. The arming of
1683 * the timeout happens in the complete handler.
1684 */
1685 cancel_delayed_work(&hdev->discov_off);
1686 hdev->discov_timeout = timeout;
1687
Johan Hedbergb456f872013-10-19 23:38:22 +03001688 /* Limited discoverable mode */
1689 if (cp->val == 0x02)
1690 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1691 else
1692 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1693
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001694 hci_req_init(&req, hdev);
1695
Johan Hedberg9a43e252013-10-20 19:00:07 +03001696 /* The procedure for LE-only controllers is much simpler - just
1697 * update the advertising data.
1698 */
1699 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1700 goto update_ad;
1701
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001702 scan = SCAN_PAGE;
1703
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001704 if (cp->val) {
1705 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001706
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001707 if (cp->val == 0x02) {
1708 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001709 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001710 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1711 hci_cp.iac_lap[1] = 0x8b;
1712 hci_cp.iac_lap[2] = 0x9e;
1713 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1714 hci_cp.iac_lap[4] = 0x8b;
1715 hci_cp.iac_lap[5] = 0x9e;
1716 } else {
1717 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001718 hci_cp.num_iac = 1;
1719 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1720 hci_cp.iac_lap[1] = 0x8b;
1721 hci_cp.iac_lap[2] = 0x9e;
1722 }
1723
1724 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1725 (hci_cp.num_iac * 3) + 1, &hci_cp);
1726
1727 scan |= SCAN_INQUIRY;
1728 } else {
1729 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1730 }
1731
1732 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001733
Johan Hedberg9a43e252013-10-20 19:00:07 +03001734update_ad:
1735 update_adv_data(&req);
1736
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001737 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001738 if (err < 0)
1739 mgmt_pending_remove(cmd);
1740
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001741failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001742 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001743 return err;
1744}
1745
Johan Hedberg406d7802013-03-15 17:07:09 -05001746static void write_fast_connectable(struct hci_request *req, bool enable)
1747{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001748 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001749 struct hci_cp_write_page_scan_activity acp;
1750 u8 type;
1751
Johan Hedberg547003b2013-10-21 16:51:53 +03001752 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1753 return;
1754
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001755 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1756 return;
1757
Johan Hedberg406d7802013-03-15 17:07:09 -05001758 if (enable) {
1759 type = PAGE_SCAN_TYPE_INTERLACED;
1760
1761 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001762 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001763 } else {
1764 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1765
1766 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001767 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001768 }
1769
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001770 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001771
Johan Hedbergbd98b992013-03-15 17:07:13 -05001772 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1773 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1774 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1775 sizeof(acp), &acp);
1776
1777 if (hdev->page_scan_type != type)
1778 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001779}
1780
Marcel Holtmann1904a852015-01-11 13:50:44 -08001781static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1782 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001783{
1784 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001785 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001786 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001787
1788 BT_DBG("status 0x%02x", status);
1789
1790 hci_dev_lock(hdev);
1791
1792 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1793 if (!cmd)
1794 goto unlock;
1795
Johan Hedberg37438c12013-10-14 16:20:05 +03001796 if (status) {
1797 u8 mgmt_err = mgmt_status(status);
1798 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1799 goto remove_cmd;
1800 }
1801
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001802 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001803 if (cp->val) {
1804 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1805 &hdev->dev_flags);
1806 discov_changed = false;
1807 } else {
1808 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1809 &hdev->dev_flags);
1810 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1811 &hdev->dev_flags);
1812 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001813
Johan Hedberg2b76f452013-03-15 17:07:04 -05001814 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1815
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001816 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001817 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001818 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001819 if (discov_changed)
1820 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001821 hci_update_background_scan(hdev);
1822 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001823
Johan Hedberg37438c12013-10-14 16:20:05 +03001824remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001825 mgmt_pending_remove(cmd);
1826
1827unlock:
1828 hci_dev_unlock(hdev);
1829}
1830
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001831static int set_connectable_update_settings(struct hci_dev *hdev,
1832 struct sock *sk, u8 val)
1833{
1834 bool changed = false;
1835 int err;
1836
1837 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1838 changed = true;
1839
1840 if (val) {
1841 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 } else {
1843 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1844 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1845 }
1846
1847 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1848 if (err < 0)
1849 return err;
1850
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001852 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001854 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001855 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001856
1857 return 0;
1858}
1859
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001860static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001861 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001862{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001863 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001864 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001865 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001866 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001867 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001868
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001869 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001870
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001871 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1872 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001874 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001875
Johan Hedberga7e80f22013-01-09 16:05:19 +02001876 if (cp->val != 0x00 && cp->val != 0x01)
1877 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1878 MGMT_STATUS_INVALID_PARAMS);
1879
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001880 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001881
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001882 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001883 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001884 goto failed;
1885 }
1886
1887 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001888 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001889 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001890 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001891 goto failed;
1892 }
1893
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001894 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1895 if (!cmd) {
1896 err = -ENOMEM;
1897 goto failed;
1898 }
1899
Johan Hedberg2b76f452013-03-15 17:07:04 -05001900 hci_req_init(&req, hdev);
1901
Johan Hedberg9a43e252013-10-20 19:00:07 +03001902 /* If BR/EDR is not enabled and we disable advertising as a
1903 * by-product of disabling connectable, we need to update the
1904 * advertising flags.
1905 */
1906 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1907 if (!cp->val) {
1908 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1909 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1910 }
1911 update_adv_data(&req);
1912 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001913 if (cp->val) {
1914 scan = SCAN_PAGE;
1915 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001916 /* If we don't have any whitelist entries just
1917 * disable all scanning. If there are entries
1918 * and we had both page and inquiry scanning
1919 * enabled then fall back to only page scanning.
1920 * Otherwise no changes are needed.
1921 */
1922 if (list_empty(&hdev->whitelist))
1923 scan = SCAN_DISABLED;
1924 else if (test_bit(HCI_ISCAN, &hdev->flags))
1925 scan = SCAN_PAGE;
1926 else
1927 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001928
1929 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001930 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001931 cancel_delayed_work(&hdev->discov_off);
1932 }
1933
1934 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1935 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001936
Johan Hedberg3bd27242014-07-28 20:53:58 +03001937no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001938 /* If we're going from non-connectable to connectable or
1939 * vice-versa when fast connectable is enabled ensure that fast
1940 * connectable gets disabled. write_fast_connectable won't do
1941 * anything if the page scan parameters are already what they
1942 * should be.
1943 */
1944 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001945 write_fast_connectable(&req, false);
1946
Johan Hedberge8b12022014-07-10 10:51:27 +03001947 /* Update the advertising parameters if necessary */
1948 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001949 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001950
Johan Hedberg2b76f452013-03-15 17:07:04 -05001951 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001953 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001954 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001955 err = set_connectable_update_settings(hdev, sk,
1956 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001957 goto failed;
1958 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001959
1960failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001961 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001962 return err;
1963}
1964
Johan Hedbergb2939472014-07-30 09:22:23 +03001965static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001966 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001967{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001968 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001969 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001970 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001972 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001973
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001975 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001976 MGMT_STATUS_INVALID_PARAMS);
1977
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001978 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001979
1980 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001983 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984
Johan Hedbergb2939472014-07-30 09:22:23 +03001985 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001988
Marcel Holtmann55594352013-10-06 16:11:57 -07001989 if (changed)
1990 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001991
Marcel Holtmann55594352013-10-06 16:11:57 -07001992unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001993 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001994 return err;
1995}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001996
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001997static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1998 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001999{
2000 struct mgmt_mode *cp = data;
2001 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002002 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002003 int err;
2004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002005 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002006
Johan Hedberge6fe7982013-10-02 15:45:22 +03002007 status = mgmt_bredr_support(hdev);
2008 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002010 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002011
Johan Hedberga7e80f22013-01-09 16:05:19 +02002012 if (cp->val != 0x00 && cp->val != 0x01)
2013 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2014 MGMT_STATUS_INVALID_PARAMS);
2015
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002016 hci_dev_lock(hdev);
2017
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002018 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002019 bool changed = false;
2020
2021 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002022 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002023 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2024 changed = true;
2025 }
2026
2027 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2028 if (err < 0)
2029 goto failed;
2030
2031 if (changed)
2032 err = new_settings(hdev, sk);
2033
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002034 goto failed;
2035 }
2036
2037 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002038 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002039 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002040 goto failed;
2041 }
2042
2043 val = !!cp->val;
2044
2045 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2046 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2047 goto failed;
2048 }
2049
2050 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2051 if (!cmd) {
2052 err = -ENOMEM;
2053 goto failed;
2054 }
2055
2056 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2057 if (err < 0) {
2058 mgmt_pending_remove(cmd);
2059 goto failed;
2060 }
2061
2062failed:
2063 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002064 return err;
2065}
2066
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002067static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002068{
2069 struct mgmt_mode *cp = data;
2070 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002071 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002072 int err;
2073
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002074 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002075
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002076 status = mgmt_bredr_support(hdev);
2077 if (status)
2078 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2079
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002080 if (!lmp_ssp_capable(hdev))
2081 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2082 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002083
Johan Hedberga7e80f22013-01-09 16:05:19 +02002084 if (cp->val != 0x00 && cp->val != 0x01)
2085 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2086 MGMT_STATUS_INVALID_PARAMS);
2087
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002088 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002089
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002090 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002092
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002093 if (cp->val) {
2094 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2095 &hdev->dev_flags);
2096 } else {
2097 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2098 &hdev->dev_flags);
2099 if (!changed)
2100 changed = test_and_clear_bit(HCI_HS_ENABLED,
2101 &hdev->dev_flags);
2102 else
2103 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002104 }
2105
2106 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2107 if (err < 0)
2108 goto failed;
2109
2110 if (changed)
2111 err = new_settings(hdev, sk);
2112
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002113 goto failed;
2114 }
2115
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002116 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2117 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002118 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2119 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002120 goto failed;
2121 }
2122
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002123 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002124 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2125 goto failed;
2126 }
2127
2128 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2129 if (!cmd) {
2130 err = -ENOMEM;
2131 goto failed;
2132 }
2133
Johan Hedberg37699722014-06-24 14:00:27 +03002134 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2135 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2136 sizeof(cp->val), &cp->val);
2137
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002138 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002139 if (err < 0) {
2140 mgmt_pending_remove(cmd);
2141 goto failed;
2142 }
2143
2144failed:
2145 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002146 return err;
2147}
2148
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002149static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002150{
2151 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002153 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002154 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002156 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002157
Johan Hedberge6fe7982013-10-02 15:45:22 +03002158 status = mgmt_bredr_support(hdev);
2159 if (status)
2160 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002161
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002162 if (!lmp_ssp_capable(hdev))
2163 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2164 MGMT_STATUS_NOT_SUPPORTED);
2165
2166 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2167 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2168 MGMT_STATUS_REJECTED);
2169
Johan Hedberga7e80f22013-01-09 16:05:19 +02002170 if (cp->val != 0x00 && cp->val != 0x01)
2171 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2172 MGMT_STATUS_INVALID_PARAMS);
2173
Marcel Holtmannee392692013-10-01 22:59:23 -07002174 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002175
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002178 } else {
2179 if (hdev_is_powered(hdev)) {
2180 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2181 MGMT_STATUS_REJECTED);
2182 goto unlock;
2183 }
2184
Marcel Holtmannee392692013-10-01 22:59:23 -07002185 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002186 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002187
2188 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2189 if (err < 0)
2190 goto unlock;
2191
2192 if (changed)
2193 err = new_settings(hdev, sk);
2194
2195unlock:
2196 hci_dev_unlock(hdev);
2197 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002198}
2199
Marcel Holtmann1904a852015-01-11 13:50:44 -08002200static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002201{
2202 struct cmd_lookup match = { NULL, hdev };
2203
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302204 hci_dev_lock(hdev);
2205
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002206 if (status) {
2207 u8 mgmt_err = mgmt_status(status);
2208
2209 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2210 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302211 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002212 }
2213
2214 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2215
2216 new_settings(hdev, match.sk);
2217
2218 if (match.sk)
2219 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002220
2221 /* Make sure the controller has a good default for
2222 * advertising data. Restrict the update to when LE
2223 * has actually been enabled. During power on, the
2224 * update in powered_update_hci will take care of it.
2225 */
2226 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2227 struct hci_request req;
2228
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002229 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002230 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002231 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002232 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002233 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302235
2236unlock:
2237 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002238}
2239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002240static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002241{
2242 struct mgmt_mode *cp = data;
2243 struct hci_cp_write_le_host_supported hci_cp;
2244 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002245 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002247 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002249 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002250
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002251 if (!lmp_le_capable(hdev))
2252 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2253 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002254
Johan Hedberga7e80f22013-01-09 16:05:19 +02002255 if (cp->val != 0x00 && cp->val != 0x01)
2256 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2257 MGMT_STATUS_INVALID_PARAMS);
2258
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002260 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002261 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2262 MGMT_STATUS_REJECTED);
2263
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002264 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002265
2266 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002267 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002269 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002270 bool changed = false;
2271
2272 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2273 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2274 changed = true;
2275 }
2276
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002277 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2278 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002279 changed = true;
2280 }
2281
Johan Hedberg06199cf2012-02-22 16:37:11 +02002282 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2283 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002284 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002285
2286 if (changed)
2287 err = new_settings(hdev, sk);
2288
Johan Hedberg1de028c2012-02-29 19:55:35 -08002289 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002290 }
2291
Johan Hedberg4375f102013-09-25 13:26:10 +03002292 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2293 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002294 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002295 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002296 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297 }
2298
2299 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2300 if (!cmd) {
2301 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002302 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002303 }
2304
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002305 hci_req_init(&req, hdev);
2306
Johan Hedberg06199cf2012-02-22 16:37:11 +02002307 memset(&hci_cp, 0, sizeof(hci_cp));
2308
2309 if (val) {
2310 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002311 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002313 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002314 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002315 }
2316
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002317 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2318 &hci_cp);
2319
2320 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302321 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002322 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002323
Johan Hedberg1de028c2012-02-29 19:55:35 -08002324unlock:
2325 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002326 return err;
2327}
2328
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002329/* This is a helper function to test for pending mgmt commands that can
2330 * cause CoD or EIR HCI commands. We can only allow one such pending
2331 * mgmt command at a time since otherwise we cannot easily track what
2332 * the current values are, will be, and based on that calculate if a new
2333 * HCI command needs to be sent and if yes with what value.
2334 */
2335static bool pending_eir_or_class(struct hci_dev *hdev)
2336{
2337 struct pending_cmd *cmd;
2338
2339 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2340 switch (cmd->opcode) {
2341 case MGMT_OP_ADD_UUID:
2342 case MGMT_OP_REMOVE_UUID:
2343 case MGMT_OP_SET_DEV_CLASS:
2344 case MGMT_OP_SET_POWERED:
2345 return true;
2346 }
2347 }
2348
2349 return false;
2350}
2351
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002352static const u8 bluetooth_base_uuid[] = {
2353 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2354 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2355};
2356
2357static u8 get_uuid_size(const u8 *uuid)
2358{
2359 u32 val;
2360
2361 if (memcmp(uuid, bluetooth_base_uuid, 12))
2362 return 128;
2363
2364 val = get_unaligned_le32(&uuid[12]);
2365 if (val > 0xffff)
2366 return 32;
2367
2368 return 16;
2369}
2370
Johan Hedberg92da6092013-03-15 17:06:55 -05002371static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2372{
2373 struct pending_cmd *cmd;
2374
2375 hci_dev_lock(hdev);
2376
2377 cmd = mgmt_pending_find(mgmt_op, hdev);
2378 if (!cmd)
2379 goto unlock;
2380
2381 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2382 hdev->dev_class, 3);
2383
2384 mgmt_pending_remove(cmd);
2385
2386unlock:
2387 hci_dev_unlock(hdev);
2388}
2389
Marcel Holtmann1904a852015-01-11 13:50:44 -08002390static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002391{
2392 BT_DBG("status 0x%02x", status);
2393
2394 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2395}
2396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002397static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002398{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002399 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002400 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002401 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002403 int err;
2404
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002405 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002407 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002409 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002410 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002411 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002412 goto failed;
2413 }
2414
Andre Guedes92c4c202012-06-07 19:05:44 -03002415 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416 if (!uuid) {
2417 err = -ENOMEM;
2418 goto failed;
2419 }
2420
2421 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002422 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002423 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedbergde66aa62013-01-27 00:31:27 +02002425 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002428
Johan Hedberg890ea892013-03-15 17:06:52 -05002429 update_class(&req);
2430 update_eir(&req);
2431
Johan Hedberg92da6092013-03-15 17:06:55 -05002432 err = hci_req_run(&req, add_uuid_complete);
2433 if (err < 0) {
2434 if (err != -ENODATA)
2435 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002436
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002437 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002438 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002439 goto failed;
2440 }
2441
2442 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002444 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002445 goto failed;
2446 }
2447
2448 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002449
2450failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002451 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002452 return err;
2453}
2454
Johan Hedberg24b78d02012-02-23 23:24:30 +02002455static bool enable_service_cache(struct hci_dev *hdev)
2456{
2457 if (!hdev_is_powered(hdev))
2458 return false;
2459
2460 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002461 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2462 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002463 return true;
2464 }
2465
2466 return false;
2467}
2468
Marcel Holtmann1904a852015-01-11 13:50:44 -08002469static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002470{
2471 BT_DBG("status 0x%02x", status);
2472
2473 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2474}
2475
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002476static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002477 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002478{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002479 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002480 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002481 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 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 -05002483 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484 int err, found;
2485
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002486 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002488 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002489
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002490 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002491 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002492 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002493 goto unlock;
2494 }
2495
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002496 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002497 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002498
Johan Hedberg24b78d02012-02-23 23:24:30 +02002499 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002500 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002501 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002502 goto unlock;
2503 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002504
Johan Hedberg9246a862012-02-23 21:33:16 +02002505 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002506 }
2507
2508 found = 0;
2509
Johan Hedberg056341c2013-01-27 00:31:30 +02002510 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002511 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2512 continue;
2513
2514 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002515 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002516 found++;
2517 }
2518
2519 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002520 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002521 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002522 goto unlock;
2523 }
2524
Johan Hedberg9246a862012-02-23 21:33:16 +02002525update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002527
Johan Hedberg890ea892013-03-15 17:06:52 -05002528 update_class(&req);
2529 update_eir(&req);
2530
Johan Hedberg92da6092013-03-15 17:06:55 -05002531 err = hci_req_run(&req, remove_uuid_complete);
2532 if (err < 0) {
2533 if (err != -ENODATA)
2534 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002535
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002536 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002537 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002538 goto unlock;
2539 }
2540
2541 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002543 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002544 goto unlock;
2545 }
2546
2547 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002548
2549unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002550 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002551 return err;
2552}
2553
Marcel Holtmann1904a852015-01-11 13:50:44 -08002554static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002555{
2556 BT_DBG("status 0x%02x", status);
2557
2558 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2559}
2560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002561static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002562 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002563{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002564 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002565 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002566 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002567 int err;
2568
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002569 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002570
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002571 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002572 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2573 MGMT_STATUS_NOT_SUPPORTED);
2574
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002575 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002576
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002577 if (pending_eir_or_class(hdev)) {
2578 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2579 MGMT_STATUS_BUSY);
2580 goto unlock;
2581 }
2582
2583 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2584 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2585 MGMT_STATUS_INVALID_PARAMS);
2586 goto unlock;
2587 }
2588
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002589 hdev->major_class = cp->major;
2590 hdev->minor_class = cp->minor;
2591
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002592 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002593 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002594 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002595 goto unlock;
2596 }
2597
Johan Hedberg890ea892013-03-15 17:06:52 -05002598 hci_req_init(&req, hdev);
2599
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002600 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002601 hci_dev_unlock(hdev);
2602 cancel_delayed_work_sync(&hdev->service_cache);
2603 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002604 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002605 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002606
Johan Hedberg890ea892013-03-15 17:06:52 -05002607 update_class(&req);
2608
Johan Hedberg92da6092013-03-15 17:06:55 -05002609 err = hci_req_run(&req, set_class_complete);
2610 if (err < 0) {
2611 if (err != -ENODATA)
2612 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002613
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002614 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002615 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002616 goto unlock;
2617 }
2618
2619 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002621 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002622 goto unlock;
2623 }
2624
2625 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002626
Johan Hedbergb5235a62012-02-21 14:32:24 +02002627unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002628 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002629 return err;
2630}
2631
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002632static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002633 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002634{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002635 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002636 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2637 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002638 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002639 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002640 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002641
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002642 BT_DBG("request for %s", hdev->name);
2643
2644 if (!lmp_bredr_capable(hdev))
2645 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2646 MGMT_STATUS_NOT_SUPPORTED);
2647
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002648 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002649 if (key_count > max_key_count) {
2650 BT_ERR("load_link_keys: too big key_count value %u",
2651 key_count);
2652 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2653 MGMT_STATUS_INVALID_PARAMS);
2654 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002655
Johan Hedberg86742e12011-11-07 23:13:38 +02002656 expected_len = sizeof(*cp) + key_count *
2657 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002658 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002659 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002660 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002661 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002662 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002663 }
2664
Johan Hedberg4ae143012013-01-20 14:27:13 +02002665 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2666 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2667 MGMT_STATUS_INVALID_PARAMS);
2668
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002669 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002670 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002671
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002672 for (i = 0; i < key_count; i++) {
2673 struct mgmt_link_key_info *key = &cp->keys[i];
2674
Marcel Holtmann8e991132014-01-10 02:07:25 -08002675 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002676 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2677 MGMT_STATUS_INVALID_PARAMS);
2678 }
2679
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002680 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002681
2682 hci_link_keys_clear(hdev);
2683
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002684 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002685 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2686 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002687 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002688 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2689 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002690
2691 if (changed)
2692 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002693
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002694 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002695 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002696
Johan Hedberg58e92932014-06-24 14:00:26 +03002697 /* Always ignore debug keys and require a new pairing if
2698 * the user wants to use them.
2699 */
2700 if (key->type == HCI_LK_DEBUG_COMBINATION)
2701 continue;
2702
Johan Hedberg7652ff62014-06-24 13:15:49 +03002703 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2704 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002705 }
2706
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002707 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002708
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002709 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002711 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002712}
2713
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002715 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002716{
2717 struct mgmt_ev_device_unpaired ev;
2718
2719 bacpy(&ev.addr.bdaddr, bdaddr);
2720 ev.addr.type = addr_type;
2721
2722 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002723 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002724}
2725
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002726static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002727 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002729 struct mgmt_cp_unpair_device *cp = data;
2730 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002731 struct hci_cp_disconnect dc;
2732 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002734 int err;
2735
Johan Hedberga8a1d192011-11-10 15:54:38 +02002736 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002737 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2738 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002739
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002740 if (!bdaddr_type_is_valid(cp->addr.type))
2741 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2742 MGMT_STATUS_INVALID_PARAMS,
2743 &rp, sizeof(rp));
2744
Johan Hedberg118da702013-01-20 14:27:20 +02002745 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2746 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2747 MGMT_STATUS_INVALID_PARAMS,
2748 &rp, sizeof(rp));
2749
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002750 hci_dev_lock(hdev);
2751
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002752 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002753 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002754 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002755 goto unlock;
2756 }
2757
Johan Hedberge0b2b272014-02-18 17:14:31 +02002758 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002759 /* If disconnection is requested, then look up the
2760 * connection. If the remote device is connected, it
2761 * will be later used to terminate the link.
2762 *
2763 * Setting it to NULL explicitly will cause no
2764 * termination of the link.
2765 */
2766 if (cp->disconnect)
2767 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2768 &cp->addr.bdaddr);
2769 else
2770 conn = NULL;
2771
Johan Hedberg124f6e32012-02-09 13:50:12 +02002772 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002773 } else {
2774 u8 addr_type;
2775
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002776 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2777 &cp->addr.bdaddr);
2778 if (conn) {
2779 /* Defer clearing up the connection parameters
2780 * until closing to give a chance of keeping
2781 * them if a repairing happens.
2782 */
2783 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2784
2785 /* If disconnection is not requested, then
2786 * clear the connection variable so that the
2787 * link is not terminated.
2788 */
2789 if (!cp->disconnect)
2790 conn = NULL;
2791 }
2792
Johan Hedberge0b2b272014-02-18 17:14:31 +02002793 if (cp->addr.type == BDADDR_LE_PUBLIC)
2794 addr_type = ADDR_LE_DEV_PUBLIC;
2795 else
2796 addr_type = ADDR_LE_DEV_RANDOM;
2797
Johan Hedberga7ec7332014-02-18 17:14:35 +02002798 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2799
Johan Hedberge0b2b272014-02-18 17:14:31 +02002800 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2801 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002802
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002803 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002804 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002805 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002806 goto unlock;
2807 }
2808
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002809 /* If the connection variable is set, then termination of the
2810 * link is requested.
2811 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002812 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002813 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002814 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002815 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002816 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002817 }
2818
Johan Hedberg124f6e32012-02-09 13:50:12 +02002819 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002820 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002821 if (!cmd) {
2822 err = -ENOMEM;
2823 goto unlock;
2824 }
2825
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002826 cmd->cmd_complete = addr_cmd_complete;
2827
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002828 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002829 dc.reason = 0x13; /* Remote User Terminated Connection */
2830 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2831 if (err < 0)
2832 mgmt_pending_remove(cmd);
2833
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002834unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002835 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002836 return err;
2837}
2838
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002839static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002840 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002841{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002842 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002843 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002844 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002845 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002846 int err;
2847
2848 BT_DBG("");
2849
Johan Hedberg06a63b12013-01-20 14:27:21 +02002850 memset(&rp, 0, sizeof(rp));
2851 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2852 rp.addr.type = cp->addr.type;
2853
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002854 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002855 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2856 MGMT_STATUS_INVALID_PARAMS,
2857 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002858
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002859 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002860
2861 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002862 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2863 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002864 goto failed;
2865 }
2866
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002867 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002868 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2869 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002870 goto failed;
2871 }
2872
Andre Guedes591f47f2012-04-24 21:02:49 -03002873 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002874 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2875 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002876 else
2877 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002878
Vishal Agarwalf9607272012-06-13 05:32:43 +05302879 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002880 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2881 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002882 goto failed;
2883 }
2884
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002885 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002886 if (!cmd) {
2887 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002888 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002889 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002890
Johan Hedbergf5818c22014-12-05 13:36:02 +02002891 cmd->cmd_complete = generic_cmd_complete;
2892
Johan Hedberge3f2f922014-08-18 20:33:33 +03002893 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002895 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002896
2897failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002898 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002899 return err;
2900}
2901
Andre Guedes57c14772012-04-24 21:02:50 -03002902static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002903{
2904 switch (link_type) {
2905 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002906 switch (addr_type) {
2907 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002908 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002909
Johan Hedberg48264f02011-11-09 13:58:58 +02002910 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002911 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002912 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002913 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002914
Johan Hedberg4c659c32011-11-07 23:13:39 +02002915 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002916 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002917 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002918 }
2919}
2920
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002921static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2922 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002923{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002924 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002925 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002926 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002927 int err;
2928 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002929
2930 BT_DBG("");
2931
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002932 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002933
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002934 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002935 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002936 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002937 goto unlock;
2938 }
2939
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002940 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002941 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2942 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002943 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002944 }
2945
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002946 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002947 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002948 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002949 err = -ENOMEM;
2950 goto unlock;
2951 }
2952
Johan Hedberg2784eb42011-01-21 13:56:35 +02002953 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002954 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002955 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2956 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002957 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002958 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002959 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002960 continue;
2961 i++;
2962 }
2963
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002964 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002965
Johan Hedberg4c659c32011-11-07 23:13:39 +02002966 /* Recalculate length in case of filtered SCO connections, etc */
2967 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002968
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002969 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002970 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002971
Johan Hedberga38528f2011-01-22 06:46:43 +02002972 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002973
2974unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002975 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002976 return err;
2977}
2978
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002979static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002980 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002981{
2982 struct pending_cmd *cmd;
2983 int err;
2984
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002985 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002986 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002987 if (!cmd)
2988 return -ENOMEM;
2989
Johan Hedbergd8457692012-02-17 14:24:57 +02002990 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002991 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002992 if (err < 0)
2993 mgmt_pending_remove(cmd);
2994
2995 return err;
2996}
2997
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002998static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002999 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003000{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003001 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003002 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003003 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003004 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003005 int err;
3006
3007 BT_DBG("");
3008
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003009 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003010
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003011 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003012 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003013 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003014 goto failed;
3015 }
3016
Johan Hedbergd8457692012-02-17 14:24:57 +02003017 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003018 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003019 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003020 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003021 goto failed;
3022 }
3023
3024 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003025 struct mgmt_cp_pin_code_neg_reply ncp;
3026
3027 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003028
3029 BT_ERR("PIN code is not 16 bytes long");
3030
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003032 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003033 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003034 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003035
3036 goto failed;
3037 }
3038
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003039 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003040 if (!cmd) {
3041 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003043 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003045 cmd->cmd_complete = addr_cmd_complete;
3046
Johan Hedbergd8457692012-02-17 14:24:57 +02003047 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003048 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003049 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003050
3051 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3052 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003053 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003054
3055failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003056 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003057 return err;
3058}
3059
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3061 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003062{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003063 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003064
3065 BT_DBG("");
3066
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003067 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3068 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3069 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3070
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003071 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003072
3073 hdev->io_capability = cp->io_capability;
3074
3075 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003076 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003077
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003078 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003079
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003080 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3081 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003082}
3083
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003084static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003085{
3086 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003087 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003088
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003089 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003090 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3091 continue;
3092
Johan Hedberge9a416b2011-02-19 12:05:56 -03003093 if (cmd->user_data != conn)
3094 continue;
3095
3096 return cmd;
3097 }
3098
3099 return NULL;
3100}
3101
Johan Hedberg9df74652014-12-19 22:26:03 +02003102static int pairing_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003103{
3104 struct mgmt_rp_pair_device rp;
3105 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003106 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003107
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003108 bacpy(&rp.addr.bdaddr, &conn->dst);
3109 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003110
Johan Hedberg9df74652014-12-19 22:26:03 +02003111 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
3112 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003113
3114 /* So we don't get further callbacks for this connection */
3115 conn->connect_cfm_cb = NULL;
3116 conn->security_cfm_cb = NULL;
3117 conn->disconn_cfm_cb = NULL;
3118
David Herrmann76a68ba2013-04-06 20:28:37 +02003119 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003120
3121 /* The device is paired so there is no need to remove
3122 * its connection parameters anymore.
3123 */
3124 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003125
3126 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003127
3128 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003129}
3130
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003131void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3132{
3133 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3134 struct pending_cmd *cmd;
3135
3136 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003137 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003138 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003139 mgmt_pending_remove(cmd);
3140 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003141}
3142
Johan Hedberge9a416b2011-02-19 12:05:56 -03003143static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3144{
3145 struct pending_cmd *cmd;
3146
3147 BT_DBG("status %u", status);
3148
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003149 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003150 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003151 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003152 return;
3153 }
3154
3155 cmd->cmd_complete(cmd, mgmt_status(status));
3156 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003157}
3158
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003159static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303160{
3161 struct pending_cmd *cmd;
3162
3163 BT_DBG("status %u", status);
3164
3165 if (!status)
3166 return;
3167
3168 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003169 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303170 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003171 return;
3172 }
3173
3174 cmd->cmd_complete(cmd, mgmt_status(status));
3175 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303176}
3177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003178static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003179 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003180{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003181 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003182 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183 struct pending_cmd *cmd;
3184 u8 sec_level, auth_type;
3185 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003186 int err;
3187
3188 BT_DBG("");
3189
Szymon Jancf950a30e2013-01-18 12:48:07 +01003190 memset(&rp, 0, sizeof(rp));
3191 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3192 rp.addr.type = cp->addr.type;
3193
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003194 if (!bdaddr_type_is_valid(cp->addr.type))
3195 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3196 MGMT_STATUS_INVALID_PARAMS,
3197 &rp, sizeof(rp));
3198
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003199 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3200 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3201 MGMT_STATUS_INVALID_PARAMS,
3202 &rp, sizeof(rp));
3203
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003204 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003205
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003206 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003207 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3208 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003209 goto unlock;
3210 }
3211
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003212 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003213 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003214
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003215 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003216 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3217 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003218 } else {
3219 u8 addr_type;
3220
3221 /* Convert from L2CAP channel address type to HCI address type
3222 */
3223 if (cp->addr.type == BDADDR_LE_PUBLIC)
3224 addr_type = ADDR_LE_DEV_PUBLIC;
3225 else
3226 addr_type = ADDR_LE_DEV_RANDOM;
3227
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003228 /* When pairing a new device, it is expected to remember
3229 * this device for future connections. Adding the connection
3230 * parameter information ahead of time allows tracking
3231 * of the slave preferred values and will speed up any
3232 * further connection establishment.
3233 *
3234 * If connection parameters already exist, then they
3235 * will be kept and this function does nothing.
3236 */
3237 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3238
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003239 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003240 sec_level, HCI_LE_CONN_TIMEOUT,
3241 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003242 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003243
Ville Tervo30e76272011-02-22 16:10:53 -03003244 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003245 int status;
3246
3247 if (PTR_ERR(conn) == -EBUSY)
3248 status = MGMT_STATUS_BUSY;
3249 else
3250 status = MGMT_STATUS_CONNECT_FAILED;
3251
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003252 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003253 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003254 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003255 goto unlock;
3256 }
3257
3258 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003259 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003260 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003261 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003262 goto unlock;
3263 }
3264
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003265 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003266 if (!cmd) {
3267 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003268 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003269 goto unlock;
3270 }
3271
Johan Hedberg04ab2742014-12-05 13:36:04 +02003272 cmd->cmd_complete = pairing_complete;
3273
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003274 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003275 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003276 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003277 conn->security_cfm_cb = pairing_complete_cb;
3278 conn->disconn_cfm_cb = pairing_complete_cb;
3279 } else {
3280 conn->connect_cfm_cb = le_pairing_complete_cb;
3281 conn->security_cfm_cb = le_pairing_complete_cb;
3282 conn->disconn_cfm_cb = le_pairing_complete_cb;
3283 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003284
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003286 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003287
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003288 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003289 hci_conn_security(conn, sec_level, auth_type, true)) {
3290 cmd->cmd_complete(cmd, 0);
3291 mgmt_pending_remove(cmd);
3292 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003293
3294 err = 0;
3295
3296unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003297 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003298 return err;
3299}
3300
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3302 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003303{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003304 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003305 struct pending_cmd *cmd;
3306 struct hci_conn *conn;
3307 int err;
3308
3309 BT_DBG("");
3310
Johan Hedberg28424702012-02-02 04:02:29 +02003311 hci_dev_lock(hdev);
3312
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003313 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003314 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003315 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003316 goto unlock;
3317 }
3318
Johan Hedberg28424702012-02-02 04:02:29 +02003319 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3320 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003321 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003322 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003323 goto unlock;
3324 }
3325
3326 conn = cmd->user_data;
3327
3328 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003329 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003330 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003331 goto unlock;
3332 }
3333
Johan Hedberga511b352014-12-11 21:45:45 +02003334 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3335 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003336
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003337 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003338 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003339unlock:
3340 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003341 return err;
3342}
3343
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003344static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003345 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003346 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003347{
Johan Hedberga5c29682011-02-19 12:05:57 -03003348 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003349 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003350 int err;
3351
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003352 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003353
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003354 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003355 err = cmd_complete(sk, hdev->id, mgmt_op,
3356 MGMT_STATUS_NOT_POWERED, addr,
3357 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003358 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003359 }
3360
Johan Hedberg1707c602013-03-15 17:07:15 -05003361 if (addr->type == BDADDR_BREDR)
3362 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003363 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003364 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003365
Johan Hedberg272d90d2012-02-09 15:26:12 +02003366 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003367 err = cmd_complete(sk, hdev->id, mgmt_op,
3368 MGMT_STATUS_NOT_CONNECTED, addr,
3369 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003370 goto done;
3371 }
3372
Johan Hedberg1707c602013-03-15 17:07:15 -05003373 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003374 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003375 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003376 err = cmd_complete(sk, hdev->id, mgmt_op,
3377 MGMT_STATUS_SUCCESS, addr,
3378 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003379 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003380 err = cmd_complete(sk, hdev->id, mgmt_op,
3381 MGMT_STATUS_FAILED, addr,
3382 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003383
Brian Gix47c15e22011-11-16 13:53:14 -08003384 goto done;
3385 }
3386
Johan Hedberg1707c602013-03-15 17:07:15 -05003387 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003388 if (!cmd) {
3389 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003390 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003391 }
3392
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003393 cmd->cmd_complete = addr_cmd_complete;
3394
Brian Gix0df4c182011-11-16 13:53:13 -08003395 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003396 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3397 struct hci_cp_user_passkey_reply cp;
3398
Johan Hedberg1707c602013-03-15 17:07:15 -05003399 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003400 cp.passkey = passkey;
3401 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3402 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003403 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3404 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003405
Johan Hedberga664b5b2011-02-19 12:06:02 -03003406 if (err < 0)
3407 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003408
Brian Gix0df4c182011-11-16 13:53:13 -08003409done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003410 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003411 return err;
3412}
3413
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303414static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3415 void *data, u16 len)
3416{
3417 struct mgmt_cp_pin_code_neg_reply *cp = data;
3418
3419 BT_DBG("");
3420
Johan Hedberg1707c602013-03-15 17:07:15 -05003421 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303422 MGMT_OP_PIN_CODE_NEG_REPLY,
3423 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3424}
3425
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003426static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3427 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003428{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003429 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003430
3431 BT_DBG("");
3432
3433 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003434 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003435 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003436
Johan Hedberg1707c602013-03-15 17:07:15 -05003437 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 MGMT_OP_USER_CONFIRM_REPLY,
3439 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003440}
3441
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003442static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003443 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003444{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003445 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003446
3447 BT_DBG("");
3448
Johan Hedberg1707c602013-03-15 17:07:15 -05003449 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003450 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3451 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003452}
3453
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003454static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3455 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003456{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003457 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003458
3459 BT_DBG("");
3460
Johan Hedberg1707c602013-03-15 17:07:15 -05003461 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003462 MGMT_OP_USER_PASSKEY_REPLY,
3463 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003464}
3465
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003466static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003467 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003468{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003469 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003470
3471 BT_DBG("");
3472
Johan Hedberg1707c602013-03-15 17:07:15 -05003473 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003474 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3475 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003476}
3477
Johan Hedberg13928972013-03-15 17:07:00 -05003478static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003479{
Johan Hedberg13928972013-03-15 17:07:00 -05003480 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003481 struct hci_cp_write_local_name cp;
3482
Johan Hedberg13928972013-03-15 17:07:00 -05003483 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003484
Johan Hedberg890ea892013-03-15 17:06:52 -05003485 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003486}
3487
Marcel Holtmann1904a852015-01-11 13:50:44 -08003488static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003489{
3490 struct mgmt_cp_set_local_name *cp;
3491 struct pending_cmd *cmd;
3492
3493 BT_DBG("status 0x%02x", status);
3494
3495 hci_dev_lock(hdev);
3496
3497 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3498 if (!cmd)
3499 goto unlock;
3500
3501 cp = cmd->param;
3502
3503 if (status)
3504 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3505 mgmt_status(status));
3506 else
3507 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3508 cp, sizeof(*cp));
3509
3510 mgmt_pending_remove(cmd);
3511
3512unlock:
3513 hci_dev_unlock(hdev);
3514}
3515
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003516static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003517 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003518{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003519 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003520 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003521 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003522 int err;
3523
3524 BT_DBG("");
3525
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003526 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003527
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003528 /* If the old values are the same as the new ones just return a
3529 * direct command complete event.
3530 */
3531 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3532 !memcmp(hdev->short_name, cp->short_name,
3533 sizeof(hdev->short_name))) {
3534 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3535 data, len);
3536 goto failed;
3537 }
3538
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003539 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003540
Johan Hedbergb5235a62012-02-21 14:32:24 +02003541 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003542 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003543
3544 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003545 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003546 if (err < 0)
3547 goto failed;
3548
3549 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003550 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003551
Johan Hedbergb5235a62012-02-21 14:32:24 +02003552 goto failed;
3553 }
3554
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003555 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003556 if (!cmd) {
3557 err = -ENOMEM;
3558 goto failed;
3559 }
3560
Johan Hedberg13928972013-03-15 17:07:00 -05003561 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3562
Johan Hedberg890ea892013-03-15 17:06:52 -05003563 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003564
3565 if (lmp_bredr_capable(hdev)) {
3566 update_name(&req);
3567 update_eir(&req);
3568 }
3569
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003570 /* The name is stored in the scan response data and so
3571 * no need to udpate the advertising data here.
3572 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003573 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003574 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003575
Johan Hedberg13928972013-03-15 17:07:00 -05003576 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003577 if (err < 0)
3578 mgmt_pending_remove(cmd);
3579
3580failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003581 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003582 return err;
3583}
3584
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003585static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003586 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003587{
Szymon Jancc35938b2011-03-22 13:12:21 +01003588 struct pending_cmd *cmd;
3589 int err;
3590
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003591 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003592
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003593 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003594
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003595 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003596 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003597 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003598 goto unlock;
3599 }
3600
Andre Guedes9a1a1992012-07-24 15:03:48 -03003601 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003602 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003603 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003604 goto unlock;
3605 }
3606
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003607 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003608 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003609 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003610 goto unlock;
3611 }
3612
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003613 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003614 if (!cmd) {
3615 err = -ENOMEM;
3616 goto unlock;
3617 }
3618
Johan Hedberg710f11c2014-05-26 11:21:22 +03003619 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003620 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3621 0, NULL);
3622 else
3623 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3624
Szymon Jancc35938b2011-03-22 13:12:21 +01003625 if (err < 0)
3626 mgmt_pending_remove(cmd);
3627
3628unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003629 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003630 return err;
3631}
3632
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003633static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003634 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003635{
Szymon Janc2763eda2011-03-22 13:12:22 +01003636 int err;
3637
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003638 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003639
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003640 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003641
Marcel Holtmannec109112014-01-10 02:07:30 -08003642 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3643 struct mgmt_cp_add_remote_oob_data *cp = data;
3644 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003645
Johan Hedbergc19a4952014-11-17 20:52:19 +02003646 if (cp->addr.type != BDADDR_BREDR) {
3647 err = cmd_complete(sk, hdev->id,
3648 MGMT_OP_ADD_REMOTE_OOB_DATA,
3649 MGMT_STATUS_INVALID_PARAMS,
3650 &cp->addr, sizeof(cp->addr));
3651 goto unlock;
3652 }
3653
Marcel Holtmannec109112014-01-10 02:07:30 -08003654 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003655 cp->addr.type, cp->hash,
3656 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003657 if (err < 0)
3658 status = MGMT_STATUS_FAILED;
3659 else
3660 status = MGMT_STATUS_SUCCESS;
3661
3662 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3663 status, &cp->addr, sizeof(cp->addr));
3664 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3665 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003666 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003667 u8 status;
3668
Johan Hedbergc19a4952014-11-17 20:52:19 +02003669 if (cp->addr.type != BDADDR_BREDR) {
3670 err = cmd_complete(sk, hdev->id,
3671 MGMT_OP_ADD_REMOTE_OOB_DATA,
3672 MGMT_STATUS_INVALID_PARAMS,
3673 &cp->addr, sizeof(cp->addr));
3674 goto unlock;
3675 }
3676
Johan Hedberg86df9202014-10-26 20:52:27 +01003677 if (bdaddr_type_is_le(cp->addr.type)) {
3678 rand192 = NULL;
3679 hash192 = NULL;
3680 } else {
3681 rand192 = cp->rand192;
3682 hash192 = cp->hash192;
3683 }
3684
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003685 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003686 cp->addr.type, hash192, rand192,
3687 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003688 if (err < 0)
3689 status = MGMT_STATUS_FAILED;
3690 else
3691 status = MGMT_STATUS_SUCCESS;
3692
3693 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3694 status, &cp->addr, sizeof(cp->addr));
3695 } else {
3696 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3697 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3698 MGMT_STATUS_INVALID_PARAMS);
3699 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003700
Johan Hedbergc19a4952014-11-17 20:52:19 +02003701unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003702 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003703 return err;
3704}
3705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003707 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003708{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003709 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003710 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003711 int err;
3712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003713 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003714
Johan Hedbergc19a4952014-11-17 20:52:19 +02003715 if (cp->addr.type != BDADDR_BREDR)
3716 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3717 MGMT_STATUS_INVALID_PARAMS,
3718 &cp->addr, sizeof(cp->addr));
3719
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003720 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003721
Johan Hedbergeedbd582014-11-15 09:34:23 +02003722 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3723 hci_remote_oob_data_clear(hdev);
3724 status = MGMT_STATUS_SUCCESS;
3725 goto done;
3726 }
3727
Johan Hedberg6928a922014-10-26 20:46:09 +01003728 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003729 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003730 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003731 else
Szymon Janca6785be2012-12-13 15:11:21 +01003732 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003733
Johan Hedbergeedbd582014-11-15 09:34:23 +02003734done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003735 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003736 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003737
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003738 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003739 return err;
3740}
3741
Marcel Holtmann80190442014-12-04 11:36:36 +01003742static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003743{
Marcel Holtmann80190442014-12-04 11:36:36 +01003744 struct hci_dev *hdev = req->hdev;
3745 struct hci_cp_le_set_scan_param param_cp;
3746 struct hci_cp_le_set_scan_enable enable_cp;
3747 struct hci_cp_inquiry inq_cp;
3748 /* General inquiry access code (GIAC) */
3749 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3750 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003751 int err;
3752
Marcel Holtmann80190442014-12-04 11:36:36 +01003753 switch (hdev->discovery.type) {
3754 case DISCOV_TYPE_BREDR:
3755 *status = mgmt_bredr_support(hdev);
3756 if (*status)
3757 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003758
Marcel Holtmann80190442014-12-04 11:36:36 +01003759 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3760 *status = MGMT_STATUS_BUSY;
3761 return false;
3762 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003763
Marcel Holtmann80190442014-12-04 11:36:36 +01003764 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003765
Marcel Holtmann80190442014-12-04 11:36:36 +01003766 memset(&inq_cp, 0, sizeof(inq_cp));
3767 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3768 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3769 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3770 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003771
Marcel Holtmann80190442014-12-04 11:36:36 +01003772 case DISCOV_TYPE_LE:
3773 case DISCOV_TYPE_INTERLEAVED:
3774 *status = mgmt_le_support(hdev);
3775 if (*status)
3776 return false;
3777
3778 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3779 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3780 *status = MGMT_STATUS_NOT_SUPPORTED;
3781 return false;
3782 }
3783
3784 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3785 /* Don't let discovery abort an outgoing
3786 * connection attempt that's using directed
3787 * advertising.
3788 */
3789 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3790 BT_CONNECT)) {
3791 *status = MGMT_STATUS_REJECTED;
3792 return false;
3793 }
3794
3795 disable_advertising(req);
3796 }
3797
3798 /* If controller is scanning, it means the background scanning
3799 * is running. Thus, we should temporarily stop it in order to
3800 * set the discovery scanning parameters.
3801 */
3802 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3803 hci_req_add_le_scan_disable(req);
3804
3805 memset(&param_cp, 0, sizeof(param_cp));
3806
3807 /* All active scans will be done with either a resolvable
3808 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003809 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003810 */
3811 err = hci_update_random_address(req, true, &own_addr_type);
3812 if (err < 0) {
3813 *status = MGMT_STATUS_FAILED;
3814 return false;
3815 }
3816
3817 param_cp.type = LE_SCAN_ACTIVE;
3818 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3819 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3820 param_cp.own_address_type = own_addr_type;
3821 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3822 &param_cp);
3823
3824 memset(&enable_cp, 0, sizeof(enable_cp));
3825 enable_cp.enable = LE_SCAN_ENABLE;
3826 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3827 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3828 &enable_cp);
3829 break;
3830
3831 default:
3832 *status = MGMT_STATUS_INVALID_PARAMS;
3833 return false;
3834 }
3835
3836 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003837}
3838
Marcel Holtmann1904a852015-01-11 13:50:44 -08003839static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3840 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003841{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003842 struct pending_cmd *cmd;
3843 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003844
Andre Guedes7c307722013-04-30 15:29:28 -03003845 BT_DBG("status %d", status);
3846
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003847 hci_dev_lock(hdev);
3848
3849 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003850 if (!cmd)
3851 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3852
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003853 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003854 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003855 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003856 }
3857
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003858 if (status) {
3859 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3860 goto unlock;
3861 }
3862
Andre Guedes7c307722013-04-30 15:29:28 -03003863 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003864
3865 switch (hdev->discovery.type) {
3866 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003867 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003868 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003869 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003870 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003871 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003872 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003873 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003874 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003875 default:
3876 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003877 timeout = 0;
3878 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003879 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003880
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003881 if (timeout)
3882 queue_delayed_work(hdev->workqueue,
3883 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003884
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003885unlock:
3886 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003887}
3888
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003889static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003890 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003891{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003892 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003893 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003894 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003895 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003896 int err;
3897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003898 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003899
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003900 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003901
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003902 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003903 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3904 MGMT_STATUS_NOT_POWERED,
3905 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003906 goto failed;
3907 }
3908
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003909 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3910 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003911 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3912 MGMT_STATUS_BUSY, &cp->type,
3913 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03003914 goto failed;
3915 }
3916
Johan Hedberg2922a942014-12-05 13:36:06 +02003917 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003918 if (!cmd) {
3919 err = -ENOMEM;
3920 goto failed;
3921 }
3922
Johan Hedberg2922a942014-12-05 13:36:06 +02003923 cmd->cmd_complete = generic_cmd_complete;
3924
Marcel Holtmann22078802014-12-05 11:45:22 +01003925 /* Clear the discovery filter first to free any previously
3926 * allocated memory for the UUID list.
3927 */
3928 hci_discovery_filter_clear(hdev);
3929
Andre Guedes4aab14e2012-02-17 20:39:36 -03003930 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003931 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003932
Andre Guedes7c307722013-04-30 15:29:28 -03003933 hci_req_init(&req, hdev);
3934
Marcel Holtmann80190442014-12-04 11:36:36 +01003935 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003936 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003937 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003938 mgmt_pending_remove(cmd);
3939 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003940 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003941
Andre Guedes7c307722013-04-30 15:29:28 -03003942 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003943 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003944 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003945 goto failed;
3946 }
3947
3948 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003949
3950failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003951 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003952 return err;
3953}
3954
Johan Hedberg9df74652014-12-19 22:26:03 +02003955static int service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03003956{
Johan Hedberg9df74652014-12-19 22:26:03 +02003957 return cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
3958 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02003959}
3960
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003961static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3962 void *data, u16 len)
3963{
3964 struct mgmt_cp_start_service_discovery *cp = data;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003965 struct pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003966 struct hci_request req;
3967 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3968 u16 uuid_count, expected_len;
3969 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03003970 int err;
3971
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003972 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003973
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003974 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03003975
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003976 if (!hdev_is_powered(hdev)) {
3977 err = cmd_complete(sk, hdev->id,
3978 MGMT_OP_START_SERVICE_DISCOVERY,
3979 MGMT_STATUS_NOT_POWERED,
3980 &cp->type, sizeof(cp->type));
3981 goto failed;
3982 }
3983
3984 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3985 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3986 err = cmd_complete(sk, hdev->id,
3987 MGMT_OP_START_SERVICE_DISCOVERY,
3988 MGMT_STATUS_BUSY, &cp->type,
3989 sizeof(cp->type));
3990 goto failed;
3991 }
3992
3993 uuid_count = __le16_to_cpu(cp->uuid_count);
3994 if (uuid_count > max_uuid_count) {
3995 BT_ERR("service_discovery: too big uuid_count value %u",
3996 uuid_count);
3997 err = cmd_complete(sk, hdev->id,
3998 MGMT_OP_START_SERVICE_DISCOVERY,
3999 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4000 sizeof(cp->type));
4001 goto failed;
4002 }
4003
4004 expected_len = sizeof(*cp) + uuid_count * 16;
4005 if (expected_len != len) {
4006 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4007 expected_len, len);
4008 err = cmd_complete(sk, hdev->id,
4009 MGMT_OP_START_SERVICE_DISCOVERY,
4010 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4011 sizeof(cp->type));
4012 goto failed;
4013 }
4014
4015 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004016 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004017 if (!cmd) {
4018 err = -ENOMEM;
4019 goto failed;
4020 }
4021
Johan Hedberg2922a942014-12-05 13:36:06 +02004022 cmd->cmd_complete = service_discovery_cmd_complete;
4023
Marcel Holtmann22078802014-12-05 11:45:22 +01004024 /* Clear the discovery filter first to free any previously
4025 * allocated memory for the UUID list.
4026 */
4027 hci_discovery_filter_clear(hdev);
4028
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004029 hdev->discovery.type = cp->type;
4030 hdev->discovery.rssi = cp->rssi;
4031 hdev->discovery.uuid_count = uuid_count;
4032
4033 if (uuid_count > 0) {
4034 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4035 GFP_KERNEL);
4036 if (!hdev->discovery.uuids) {
4037 err = cmd_complete(sk, hdev->id,
4038 MGMT_OP_START_SERVICE_DISCOVERY,
4039 MGMT_STATUS_FAILED,
4040 &cp->type, sizeof(cp->type));
4041 mgmt_pending_remove(cmd);
4042 goto failed;
4043 }
4044 }
4045
4046 hci_req_init(&req, hdev);
4047
4048 if (!trigger_discovery(&req, &status)) {
4049 err = cmd_complete(sk, hdev->id,
4050 MGMT_OP_START_SERVICE_DISCOVERY,
4051 status, &cp->type, sizeof(cp->type));
4052 mgmt_pending_remove(cmd);
4053 goto failed;
4054 }
4055
4056 err = hci_req_run(&req, start_discovery_complete);
4057 if (err < 0) {
4058 mgmt_pending_remove(cmd);
4059 goto failed;
4060 }
4061
4062 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4063
4064failed:
4065 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004066 return err;
4067}
4068
Marcel Holtmann1904a852015-01-11 13:50:44 -08004069static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004070{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004071 struct pending_cmd *cmd;
4072
Andre Guedes0e05bba2013-04-30 15:29:33 -03004073 BT_DBG("status %d", status);
4074
4075 hci_dev_lock(hdev);
4076
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004077 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4078 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004079 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004080 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004081 }
4082
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004083 if (!status)
4084 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004085
Andre Guedes0e05bba2013-04-30 15:29:33 -03004086 hci_dev_unlock(hdev);
4087}
4088
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004089static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004090 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004091{
Johan Hedbergd9306502012-02-20 23:25:18 +02004092 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004093 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004094 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004095 int err;
4096
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004097 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004098
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004099 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004100
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004101 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004102 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004103 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4104 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004105 goto unlock;
4106 }
4107
4108 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004109 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004110 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4111 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004112 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004113 }
4114
Johan Hedberg2922a942014-12-05 13:36:06 +02004115 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004116 if (!cmd) {
4117 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004118 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004119 }
4120
Johan Hedberg2922a942014-12-05 13:36:06 +02004121 cmd->cmd_complete = generic_cmd_complete;
4122
Andre Guedes0e05bba2013-04-30 15:29:33 -03004123 hci_req_init(&req, hdev);
4124
Johan Hedberg21a60d32014-06-10 14:05:58 +03004125 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004126
Johan Hedberg21a60d32014-06-10 14:05:58 +03004127 err = hci_req_run(&req, stop_discovery_complete);
4128 if (!err) {
4129 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004130 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004131 }
4132
Johan Hedberg21a60d32014-06-10 14:05:58 +03004133 mgmt_pending_remove(cmd);
4134
4135 /* If no HCI commands were sent we're done */
4136 if (err == -ENODATA) {
4137 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4138 &mgmt_cp->type, sizeof(mgmt_cp->type));
4139 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4140 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004141
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004142unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004143 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004144 return err;
4145}
4146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004147static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004148 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004149{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004150 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004151 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004152 int err;
4153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004154 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004155
Johan Hedberg561aafb2012-01-04 13:31:59 +02004156 hci_dev_lock(hdev);
4157
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004158 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004159 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4160 MGMT_STATUS_FAILED, &cp->addr,
4161 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004162 goto failed;
4163 }
4164
Johan Hedberga198e7b2012-02-17 14:27:06 +02004165 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004166 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004167 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4168 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4169 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004170 goto failed;
4171 }
4172
4173 if (cp->name_known) {
4174 e->name_state = NAME_KNOWN;
4175 list_del(&e->list);
4176 } else {
4177 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004178 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004179 }
4180
Johan Hedberge3846622013-01-09 15:29:33 +02004181 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4182 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004183
4184failed:
4185 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004186 return err;
4187}
4188
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004189static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004190 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004191{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004192 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004193 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004194 int err;
4195
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004196 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004197
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004198 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004199 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4200 MGMT_STATUS_INVALID_PARAMS,
4201 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004202
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004203 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004204
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004205 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4206 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004207 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004208 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004209 goto done;
4210 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004211
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004212 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4213 sk);
4214 status = MGMT_STATUS_SUCCESS;
4215
4216done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004217 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004218 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004219
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004220 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004221
4222 return err;
4223}
4224
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004225static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004226 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004227{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004228 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004229 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004230 int err;
4231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004232 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004233
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004234 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004235 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4236 MGMT_STATUS_INVALID_PARAMS,
4237 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004238
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004239 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004240
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004241 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4242 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004243 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004244 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004245 goto done;
4246 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004247
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004248 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4249 sk);
4250 status = MGMT_STATUS_SUCCESS;
4251
4252done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004253 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004254 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004255
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004256 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004257
4258 return err;
4259}
4260
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004261static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4262 u16 len)
4263{
4264 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004265 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004266 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004267 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004268
4269 BT_DBG("%s", hdev->name);
4270
Szymon Jancc72d4b82012-03-16 16:02:57 +01004271 source = __le16_to_cpu(cp->source);
4272
4273 if (source > 0x0002)
4274 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4275 MGMT_STATUS_INVALID_PARAMS);
4276
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004277 hci_dev_lock(hdev);
4278
Szymon Jancc72d4b82012-03-16 16:02:57 +01004279 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004280 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4281 hdev->devid_product = __le16_to_cpu(cp->product);
4282 hdev->devid_version = __le16_to_cpu(cp->version);
4283
4284 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4285
Johan Hedberg890ea892013-03-15 17:06:52 -05004286 hci_req_init(&req, hdev);
4287 update_eir(&req);
4288 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004289
4290 hci_dev_unlock(hdev);
4291
4292 return err;
4293}
4294
Marcel Holtmann1904a852015-01-11 13:50:44 -08004295static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4296 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004297{
4298 struct cmd_lookup match = { NULL, hdev };
4299
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304300 hci_dev_lock(hdev);
4301
Johan Hedberg4375f102013-09-25 13:26:10 +03004302 if (status) {
4303 u8 mgmt_err = mgmt_status(status);
4304
4305 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4306 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304307 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004308 }
4309
Johan Hedbergc93bd152014-07-08 15:07:48 +03004310 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4311 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4312 else
4313 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4314
Johan Hedberg4375f102013-09-25 13:26:10 +03004315 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4316 &match);
4317
4318 new_settings(hdev, match.sk);
4319
4320 if (match.sk)
4321 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304322
4323unlock:
4324 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004325}
4326
Marcel Holtmann21b51872013-10-10 09:47:53 -07004327static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4328 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004329{
4330 struct mgmt_mode *cp = data;
4331 struct pending_cmd *cmd;
4332 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004333 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004334 int err;
4335
4336 BT_DBG("request for %s", hdev->name);
4337
Johan Hedberge6fe7982013-10-02 15:45:22 +03004338 status = mgmt_le_support(hdev);
4339 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004340 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004341 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004342
4343 if (cp->val != 0x00 && cp->val != 0x01)
4344 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4345 MGMT_STATUS_INVALID_PARAMS);
4346
4347 hci_dev_lock(hdev);
4348
4349 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004350 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004351
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004352 /* The following conditions are ones which mean that we should
4353 * not do any HCI communication but directly send a mgmt
4354 * response to user space (after toggling the flag if
4355 * necessary).
4356 */
4357 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004358 hci_conn_num(hdev, LE_LINK) > 0 ||
4359 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4360 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004361 bool changed = false;
4362
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004363 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4364 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004365 changed = true;
4366 }
4367
4368 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4369 if (err < 0)
4370 goto unlock;
4371
4372 if (changed)
4373 err = new_settings(hdev, sk);
4374
4375 goto unlock;
4376 }
4377
4378 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4379 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4380 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4381 MGMT_STATUS_BUSY);
4382 goto unlock;
4383 }
4384
4385 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4386 if (!cmd) {
4387 err = -ENOMEM;
4388 goto unlock;
4389 }
4390
4391 hci_req_init(&req, hdev);
4392
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004393 if (val)
4394 enable_advertising(&req);
4395 else
4396 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004397
4398 err = hci_req_run(&req, set_advertising_complete);
4399 if (err < 0)
4400 mgmt_pending_remove(cmd);
4401
4402unlock:
4403 hci_dev_unlock(hdev);
4404 return err;
4405}
4406
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004407static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4408 void *data, u16 len)
4409{
4410 struct mgmt_cp_set_static_address *cp = data;
4411 int err;
4412
4413 BT_DBG("%s", hdev->name);
4414
Marcel Holtmann62af4442013-10-02 22:10:32 -07004415 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004416 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004417 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004418
4419 if (hdev_is_powered(hdev))
4420 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4421 MGMT_STATUS_REJECTED);
4422
4423 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4424 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4425 return cmd_status(sk, hdev->id,
4426 MGMT_OP_SET_STATIC_ADDRESS,
4427 MGMT_STATUS_INVALID_PARAMS);
4428
4429 /* Two most significant bits shall be set */
4430 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4431 return cmd_status(sk, hdev->id,
4432 MGMT_OP_SET_STATIC_ADDRESS,
4433 MGMT_STATUS_INVALID_PARAMS);
4434 }
4435
4436 hci_dev_lock(hdev);
4437
4438 bacpy(&hdev->static_addr, &cp->bdaddr);
4439
4440 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4441
4442 hci_dev_unlock(hdev);
4443
4444 return err;
4445}
4446
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004447static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4448 void *data, u16 len)
4449{
4450 struct mgmt_cp_set_scan_params *cp = data;
4451 __u16 interval, window;
4452 int err;
4453
4454 BT_DBG("%s", hdev->name);
4455
4456 if (!lmp_le_capable(hdev))
4457 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4458 MGMT_STATUS_NOT_SUPPORTED);
4459
4460 interval = __le16_to_cpu(cp->interval);
4461
4462 if (interval < 0x0004 || interval > 0x4000)
4463 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4464 MGMT_STATUS_INVALID_PARAMS);
4465
4466 window = __le16_to_cpu(cp->window);
4467
4468 if (window < 0x0004 || window > 0x4000)
4469 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4470 MGMT_STATUS_INVALID_PARAMS);
4471
Marcel Holtmann899e1072013-10-14 09:55:32 -07004472 if (window > interval)
4473 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4474 MGMT_STATUS_INVALID_PARAMS);
4475
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004476 hci_dev_lock(hdev);
4477
4478 hdev->le_scan_interval = interval;
4479 hdev->le_scan_window = window;
4480
4481 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4482
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004483 /* If background scan is running, restart it so new parameters are
4484 * loaded.
4485 */
4486 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4487 hdev->discovery.state == DISCOVERY_STOPPED) {
4488 struct hci_request req;
4489
4490 hci_req_init(&req, hdev);
4491
4492 hci_req_add_le_scan_disable(&req);
4493 hci_req_add_le_passive_scan(&req);
4494
4495 hci_req_run(&req, NULL);
4496 }
4497
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004498 hci_dev_unlock(hdev);
4499
4500 return err;
4501}
4502
Marcel Holtmann1904a852015-01-11 13:50:44 -08004503static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4504 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004505{
4506 struct pending_cmd *cmd;
4507
4508 BT_DBG("status 0x%02x", status);
4509
4510 hci_dev_lock(hdev);
4511
4512 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4513 if (!cmd)
4514 goto unlock;
4515
4516 if (status) {
4517 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4518 mgmt_status(status));
4519 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004520 struct mgmt_mode *cp = cmd->param;
4521
4522 if (cp->val)
4523 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4524 else
4525 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4526
Johan Hedberg33e38b32013-03-15 17:07:05 -05004527 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4528 new_settings(hdev, cmd->sk);
4529 }
4530
4531 mgmt_pending_remove(cmd);
4532
4533unlock:
4534 hci_dev_unlock(hdev);
4535}
4536
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004537static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004538 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004539{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004540 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004541 struct pending_cmd *cmd;
4542 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004543 int err;
4544
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004545 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004546
Johan Hedberg56f87902013-10-02 13:43:13 +03004547 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4548 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004549 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4550 MGMT_STATUS_NOT_SUPPORTED);
4551
Johan Hedberga7e80f22013-01-09 16:05:19 +02004552 if (cp->val != 0x00 && cp->val != 0x01)
4553 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4554 MGMT_STATUS_INVALID_PARAMS);
4555
Johan Hedberg5400c042012-02-21 16:40:33 +02004556 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004557 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004558 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004559
4560 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004561 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004562 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004563
4564 hci_dev_lock(hdev);
4565
Johan Hedberg05cbf292013-03-15 17:07:07 -05004566 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4567 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4568 MGMT_STATUS_BUSY);
4569 goto unlock;
4570 }
4571
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004572 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4573 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4574 hdev);
4575 goto unlock;
4576 }
4577
Johan Hedberg33e38b32013-03-15 17:07:05 -05004578 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4579 data, len);
4580 if (!cmd) {
4581 err = -ENOMEM;
4582 goto unlock;
4583 }
4584
4585 hci_req_init(&req, hdev);
4586
Johan Hedberg406d7802013-03-15 17:07:09 -05004587 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004588
4589 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004590 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004591 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004592 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004593 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004594 }
4595
Johan Hedberg33e38b32013-03-15 17:07:05 -05004596unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004597 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004598
Antti Julkuf6422ec2011-06-22 13:11:56 +03004599 return err;
4600}
4601
Marcel Holtmann1904a852015-01-11 13:50:44 -08004602static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004603{
4604 struct pending_cmd *cmd;
4605
4606 BT_DBG("status 0x%02x", status);
4607
4608 hci_dev_lock(hdev);
4609
4610 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4611 if (!cmd)
4612 goto unlock;
4613
4614 if (status) {
4615 u8 mgmt_err = mgmt_status(status);
4616
4617 /* We need to restore the flag if related HCI commands
4618 * failed.
4619 */
4620 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4621
4622 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4623 } else {
4624 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4625 new_settings(hdev, cmd->sk);
4626 }
4627
4628 mgmt_pending_remove(cmd);
4629
4630unlock:
4631 hci_dev_unlock(hdev);
4632}
4633
4634static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4635{
4636 struct mgmt_mode *cp = data;
4637 struct pending_cmd *cmd;
4638 struct hci_request req;
4639 int err;
4640
4641 BT_DBG("request for %s", hdev->name);
4642
4643 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4644 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4645 MGMT_STATUS_NOT_SUPPORTED);
4646
4647 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4648 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4649 MGMT_STATUS_REJECTED);
4650
4651 if (cp->val != 0x00 && cp->val != 0x01)
4652 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4653 MGMT_STATUS_INVALID_PARAMS);
4654
4655 hci_dev_lock(hdev);
4656
4657 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4658 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4659 goto unlock;
4660 }
4661
4662 if (!hdev_is_powered(hdev)) {
4663 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004664 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4665 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4666 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4667 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4668 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4669 }
4670
4671 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4672
4673 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4674 if (err < 0)
4675 goto unlock;
4676
4677 err = new_settings(hdev, sk);
4678 goto unlock;
4679 }
4680
4681 /* Reject disabling when powered on */
4682 if (!cp->val) {
4683 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4684 MGMT_STATUS_REJECTED);
4685 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004686 } else {
4687 /* When configuring a dual-mode controller to operate
4688 * with LE only and using a static address, then switching
4689 * BR/EDR back on is not allowed.
4690 *
4691 * Dual-mode controllers shall operate with the public
4692 * address as its identity address for BR/EDR and LE. So
4693 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004694 *
4695 * The same restrictions applies when secure connections
4696 * has been enabled. For BR/EDR this is a controller feature
4697 * while for LE it is a host stack feature. This means that
4698 * switching BR/EDR back on when secure connections has been
4699 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004700 */
4701 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004702 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
4703 test_bit(HCI_SC_ENABLED, &hdev->dev_flags))) {
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004704 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4705 MGMT_STATUS_REJECTED);
4706 goto unlock;
4707 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004708 }
4709
4710 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4711 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4712 MGMT_STATUS_BUSY);
4713 goto unlock;
4714 }
4715
4716 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4717 if (!cmd) {
4718 err = -ENOMEM;
4719 goto unlock;
4720 }
4721
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004722 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004723 * generates the correct flags.
4724 */
4725 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4726
4727 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004728
Johan Hedberg432df052014-08-01 11:13:31 +03004729 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004730 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004731
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004732 /* Since only the advertising data flags will change, there
4733 * is no need to update the scan response data.
4734 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004735 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004736
Johan Hedberg0663ca22013-10-02 13:43:14 +03004737 err = hci_req_run(&req, set_bredr_complete);
4738 if (err < 0)
4739 mgmt_pending_remove(cmd);
4740
4741unlock:
4742 hci_dev_unlock(hdev);
4743 return err;
4744}
4745
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004746static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4747 void *data, u16 len)
4748{
4749 struct mgmt_mode *cp = data;
4750 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004751 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004752 int err;
4753
4754 BT_DBG("request for %s", hdev->name);
4755
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004756 if (!lmp_sc_capable(hdev) &&
4757 !test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004758 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4759 MGMT_STATUS_NOT_SUPPORTED);
4760
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004761 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) &&
4762 !test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
4763 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4764 MGMT_STATUS_REJECTED);
4765
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004766 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004767 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4768 MGMT_STATUS_INVALID_PARAMS);
4769
4770 hci_dev_lock(hdev);
4771
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004772 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Johan Hedberga3209692014-05-26 11:23:35 +03004773 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004774 bool changed;
4775
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004776 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004777 changed = !test_and_set_bit(HCI_SC_ENABLED,
4778 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004779 if (cp->val == 0x02)
4780 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4781 else
4782 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4783 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004784 changed = test_and_clear_bit(HCI_SC_ENABLED,
4785 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004786 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4787 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004788
4789 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4790 if (err < 0)
4791 goto failed;
4792
4793 if (changed)
4794 err = new_settings(hdev, sk);
4795
4796 goto failed;
4797 }
4798
4799 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4800 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4801 MGMT_STATUS_BUSY);
4802 goto failed;
4803 }
4804
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004805 val = !!cp->val;
4806
4807 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4808 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004809 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4810 goto failed;
4811 }
4812
4813 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4814 if (!cmd) {
4815 err = -ENOMEM;
4816 goto failed;
4817 }
4818
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004819 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004820 if (err < 0) {
4821 mgmt_pending_remove(cmd);
4822 goto failed;
4823 }
4824
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004825 if (cp->val == 0x02)
4826 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4827 else
4828 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4829
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004830failed:
4831 hci_dev_unlock(hdev);
4832 return err;
4833}
4834
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004835static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4836 void *data, u16 len)
4837{
4838 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004839 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004840 int err;
4841
4842 BT_DBG("request for %s", hdev->name);
4843
Johan Hedbergb97109792014-06-24 14:00:28 +03004844 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004845 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4846 MGMT_STATUS_INVALID_PARAMS);
4847
4848 hci_dev_lock(hdev);
4849
4850 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004851 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4852 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004853 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004854 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4855 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004856
Johan Hedbergb97109792014-06-24 14:00:28 +03004857 if (cp->val == 0x02)
4858 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4859 &hdev->dev_flags);
4860 else
4861 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4862 &hdev->dev_flags);
4863
4864 if (hdev_is_powered(hdev) && use_changed &&
4865 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4866 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4867 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4868 sizeof(mode), &mode);
4869 }
4870
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004871 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4872 if (err < 0)
4873 goto unlock;
4874
4875 if (changed)
4876 err = new_settings(hdev, sk);
4877
4878unlock:
4879 hci_dev_unlock(hdev);
4880 return err;
4881}
4882
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004883static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4884 u16 len)
4885{
4886 struct mgmt_cp_set_privacy *cp = cp_data;
4887 bool changed;
4888 int err;
4889
4890 BT_DBG("request for %s", hdev->name);
4891
4892 if (!lmp_le_capable(hdev))
4893 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4894 MGMT_STATUS_NOT_SUPPORTED);
4895
4896 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4897 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4898 MGMT_STATUS_INVALID_PARAMS);
4899
4900 if (hdev_is_powered(hdev))
4901 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4902 MGMT_STATUS_REJECTED);
4903
4904 hci_dev_lock(hdev);
4905
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004906 /* If user space supports this command it is also expected to
4907 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4908 */
4909 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4910
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004911 if (cp->privacy) {
4912 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4913 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4914 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4915 } else {
4916 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4917 memset(hdev->irk, 0, sizeof(hdev->irk));
4918 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4919 }
4920
4921 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4922 if (err < 0)
4923 goto unlock;
4924
4925 if (changed)
4926 err = new_settings(hdev, sk);
4927
4928unlock:
4929 hci_dev_unlock(hdev);
4930 return err;
4931}
4932
Johan Hedberg41edf162014-02-18 10:19:35 +02004933static bool irk_is_valid(struct mgmt_irk_info *irk)
4934{
4935 switch (irk->addr.type) {
4936 case BDADDR_LE_PUBLIC:
4937 return true;
4938
4939 case BDADDR_LE_RANDOM:
4940 /* Two most significant bits shall be set */
4941 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4942 return false;
4943 return true;
4944 }
4945
4946 return false;
4947}
4948
4949static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4950 u16 len)
4951{
4952 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004953 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4954 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004955 u16 irk_count, expected_len;
4956 int i, err;
4957
4958 BT_DBG("request for %s", hdev->name);
4959
4960 if (!lmp_le_capable(hdev))
4961 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4962 MGMT_STATUS_NOT_SUPPORTED);
4963
4964 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004965 if (irk_count > max_irk_count) {
4966 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4967 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4968 MGMT_STATUS_INVALID_PARAMS);
4969 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004970
4971 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4972 if (expected_len != len) {
4973 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004974 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004975 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4976 MGMT_STATUS_INVALID_PARAMS);
4977 }
4978
4979 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4980
4981 for (i = 0; i < irk_count; i++) {
4982 struct mgmt_irk_info *key = &cp->irks[i];
4983
4984 if (!irk_is_valid(key))
4985 return cmd_status(sk, hdev->id,
4986 MGMT_OP_LOAD_IRKS,
4987 MGMT_STATUS_INVALID_PARAMS);
4988 }
4989
4990 hci_dev_lock(hdev);
4991
4992 hci_smp_irks_clear(hdev);
4993
4994 for (i = 0; i < irk_count; i++) {
4995 struct mgmt_irk_info *irk = &cp->irks[i];
4996 u8 addr_type;
4997
4998 if (irk->addr.type == BDADDR_LE_PUBLIC)
4999 addr_type = ADDR_LE_DEV_PUBLIC;
5000 else
5001 addr_type = ADDR_LE_DEV_RANDOM;
5002
5003 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5004 BDADDR_ANY);
5005 }
5006
5007 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
5008
5009 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
5010
5011 hci_dev_unlock(hdev);
5012
5013 return err;
5014}
5015
Johan Hedberg3f706b72013-01-20 14:27:16 +02005016static bool ltk_is_valid(struct mgmt_ltk_info *key)
5017{
5018 if (key->master != 0x00 && key->master != 0x01)
5019 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005020
5021 switch (key->addr.type) {
5022 case BDADDR_LE_PUBLIC:
5023 return true;
5024
5025 case BDADDR_LE_RANDOM:
5026 /* Two most significant bits shall be set */
5027 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5028 return false;
5029 return true;
5030 }
5031
5032 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005033}
5034
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005035static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005036 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005037{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005038 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005039 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5040 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005041 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005042 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005043
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005044 BT_DBG("request for %s", hdev->name);
5045
5046 if (!lmp_le_capable(hdev))
5047 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5048 MGMT_STATUS_NOT_SUPPORTED);
5049
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005050 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005051 if (key_count > max_key_count) {
5052 BT_ERR("load_ltks: too big key_count value %u", key_count);
5053 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5054 MGMT_STATUS_INVALID_PARAMS);
5055 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005056
5057 expected_len = sizeof(*cp) + key_count *
5058 sizeof(struct mgmt_ltk_info);
5059 if (expected_len != len) {
5060 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005061 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005062 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005063 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005064 }
5065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005066 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005067
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005068 for (i = 0; i < key_count; i++) {
5069 struct mgmt_ltk_info *key = &cp->keys[i];
5070
Johan Hedberg3f706b72013-01-20 14:27:16 +02005071 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005072 return cmd_status(sk, hdev->id,
5073 MGMT_OP_LOAD_LONG_TERM_KEYS,
5074 MGMT_STATUS_INVALID_PARAMS);
5075 }
5076
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005077 hci_dev_lock(hdev);
5078
5079 hci_smp_ltks_clear(hdev);
5080
5081 for (i = 0; i < key_count; i++) {
5082 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005083 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005084
5085 if (key->addr.type == BDADDR_LE_PUBLIC)
5086 addr_type = ADDR_LE_DEV_PUBLIC;
5087 else
5088 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005089
Johan Hedberg61b43352014-05-29 19:36:53 +03005090 switch (key->type) {
5091 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005092 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005093 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005094 break;
5095 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005096 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005097 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005098 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005099 case MGMT_LTK_P256_UNAUTH:
5100 authenticated = 0x00;
5101 type = SMP_LTK_P256;
5102 break;
5103 case MGMT_LTK_P256_AUTH:
5104 authenticated = 0x01;
5105 type = SMP_LTK_P256;
5106 break;
5107 case MGMT_LTK_P256_DEBUG:
5108 authenticated = 0x00;
5109 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005110 default:
5111 continue;
5112 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005113
Johan Hedberg35d70272014-02-19 14:57:47 +02005114 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005115 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005116 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005117 }
5118
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005119 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5120 NULL, 0);
5121
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005122 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005123
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005124 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005125}
5126
Johan Hedberg9df74652014-12-19 22:26:03 +02005127static int conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005128{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005129 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005130 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005131 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005132
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005133 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005134
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005135 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005136 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005137 rp.tx_power = conn->tx_power;
5138 rp.max_tx_power = conn->max_tx_power;
5139 } else {
5140 rp.rssi = HCI_RSSI_INVALID;
5141 rp.tx_power = HCI_TX_POWER_INVALID;
5142 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005143 }
5144
Johan Hedberg9df74652014-12-19 22:26:03 +02005145 err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5146 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005147
5148 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005149 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005150
5151 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005152}
5153
Marcel Holtmann1904a852015-01-11 13:50:44 -08005154static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5155 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005156{
5157 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005158 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005159 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005160 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005161 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005162
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005163 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005164
5165 hci_dev_lock(hdev);
5166
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005167 /* Commands sent in request are either Read RSSI or Read Transmit Power
5168 * Level so we check which one was last sent to retrieve connection
5169 * handle. Both commands have handle as first parameter so it's safe to
5170 * cast data on the same command struct.
5171 *
5172 * First command sent is always Read RSSI and we fail only if it fails.
5173 * In other case we simply override error to indicate success as we
5174 * already remembered if TX power value is actually valid.
5175 */
5176 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5177 if (!cp) {
5178 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005179 status = MGMT_STATUS_SUCCESS;
5180 } else {
5181 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005182 }
5183
5184 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005185 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005186 goto unlock;
5187 }
5188
5189 handle = __le16_to_cpu(cp->handle);
5190 conn = hci_conn_hash_lookup_handle(hdev, handle);
5191 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005192 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005193 goto unlock;
5194 }
5195
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005196 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5197 if (!cmd)
5198 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005199
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005200 cmd->cmd_complete(cmd, status);
5201 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005202
5203unlock:
5204 hci_dev_unlock(hdev);
5205}
5206
5207static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5208 u16 len)
5209{
5210 struct mgmt_cp_get_conn_info *cp = data;
5211 struct mgmt_rp_get_conn_info rp;
5212 struct hci_conn *conn;
5213 unsigned long conn_info_age;
5214 int err = 0;
5215
5216 BT_DBG("%s", hdev->name);
5217
5218 memset(&rp, 0, sizeof(rp));
5219 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5220 rp.addr.type = cp->addr.type;
5221
5222 if (!bdaddr_type_is_valid(cp->addr.type))
5223 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5224 MGMT_STATUS_INVALID_PARAMS,
5225 &rp, sizeof(rp));
5226
5227 hci_dev_lock(hdev);
5228
5229 if (!hdev_is_powered(hdev)) {
5230 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5231 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5232 goto unlock;
5233 }
5234
5235 if (cp->addr.type == BDADDR_BREDR)
5236 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5237 &cp->addr.bdaddr);
5238 else
5239 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5240
5241 if (!conn || conn->state != BT_CONNECTED) {
5242 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5243 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5244 goto unlock;
5245 }
5246
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005247 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5248 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5249 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5250 goto unlock;
5251 }
5252
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005253 /* To avoid client trying to guess when to poll again for information we
5254 * calculate conn info age as random value between min/max set in hdev.
5255 */
5256 conn_info_age = hdev->conn_info_min_age +
5257 prandom_u32_max(hdev->conn_info_max_age -
5258 hdev->conn_info_min_age);
5259
5260 /* Query controller to refresh cached values if they are too old or were
5261 * never read.
5262 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005263 if (time_after(jiffies, conn->conn_info_timestamp +
5264 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005265 !conn->conn_info_timestamp) {
5266 struct hci_request req;
5267 struct hci_cp_read_tx_power req_txp_cp;
5268 struct hci_cp_read_rssi req_rssi_cp;
5269 struct pending_cmd *cmd;
5270
5271 hci_req_init(&req, hdev);
5272 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5273 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5274 &req_rssi_cp);
5275
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005276 /* For LE links TX power does not change thus we don't need to
5277 * query for it once value is known.
5278 */
5279 if (!bdaddr_type_is_le(cp->addr.type) ||
5280 conn->tx_power == HCI_TX_POWER_INVALID) {
5281 req_txp_cp.handle = cpu_to_le16(conn->handle);
5282 req_txp_cp.type = 0x00;
5283 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5284 sizeof(req_txp_cp), &req_txp_cp);
5285 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005286
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005287 /* Max TX power needs to be read only once per connection */
5288 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5289 req_txp_cp.handle = cpu_to_le16(conn->handle);
5290 req_txp_cp.type = 0x01;
5291 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5292 sizeof(req_txp_cp), &req_txp_cp);
5293 }
5294
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005295 err = hci_req_run(&req, conn_info_refresh_complete);
5296 if (err < 0)
5297 goto unlock;
5298
5299 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5300 data, len);
5301 if (!cmd) {
5302 err = -ENOMEM;
5303 goto unlock;
5304 }
5305
5306 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005307 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005308 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005309
5310 conn->conn_info_timestamp = jiffies;
5311 } else {
5312 /* Cache is valid, just reply with values cached in hci_conn */
5313 rp.rssi = conn->rssi;
5314 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005315 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005316
5317 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5318 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5319 }
5320
5321unlock:
5322 hci_dev_unlock(hdev);
5323 return err;
5324}
5325
Johan Hedberg9df74652014-12-19 22:26:03 +02005326static int clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005327{
5328 struct hci_conn *conn = cmd->user_data;
5329 struct mgmt_rp_get_clock_info rp;
5330 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005331 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005332
5333 memset(&rp, 0, sizeof(rp));
5334 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5335
5336 if (status)
5337 goto complete;
5338
5339 hdev = hci_dev_get(cmd->index);
5340 if (hdev) {
5341 rp.local_clock = cpu_to_le32(hdev->clock);
5342 hci_dev_put(hdev);
5343 }
5344
5345 if (conn) {
5346 rp.piconet_clock = cpu_to_le32(conn->clock);
5347 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5348 }
5349
5350complete:
Johan Hedberg9df74652014-12-19 22:26:03 +02005351 err = cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5352 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005353
5354 if (conn) {
5355 hci_conn_drop(conn);
5356 hci_conn_put(conn);
5357 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005358
5359 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005360}
5361
Marcel Holtmann1904a852015-01-11 13:50:44 -08005362static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005363{
Johan Hedberg95868422014-06-28 17:54:07 +03005364 struct hci_cp_read_clock *hci_cp;
5365 struct pending_cmd *cmd;
5366 struct hci_conn *conn;
5367
5368 BT_DBG("%s status %u", hdev->name, status);
5369
5370 hci_dev_lock(hdev);
5371
5372 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5373 if (!hci_cp)
5374 goto unlock;
5375
5376 if (hci_cp->which) {
5377 u16 handle = __le16_to_cpu(hci_cp->handle);
5378 conn = hci_conn_hash_lookup_handle(hdev, handle);
5379 } else {
5380 conn = NULL;
5381 }
5382
5383 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5384 if (!cmd)
5385 goto unlock;
5386
Johan Hedberg69487372014-12-05 13:36:07 +02005387 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005388 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005389
5390unlock:
5391 hci_dev_unlock(hdev);
5392}
5393
5394static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5395 u16 len)
5396{
5397 struct mgmt_cp_get_clock_info *cp = data;
5398 struct mgmt_rp_get_clock_info rp;
5399 struct hci_cp_read_clock hci_cp;
5400 struct pending_cmd *cmd;
5401 struct hci_request req;
5402 struct hci_conn *conn;
5403 int err;
5404
5405 BT_DBG("%s", hdev->name);
5406
5407 memset(&rp, 0, sizeof(rp));
5408 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5409 rp.addr.type = cp->addr.type;
5410
5411 if (cp->addr.type != BDADDR_BREDR)
5412 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5413 MGMT_STATUS_INVALID_PARAMS,
5414 &rp, sizeof(rp));
5415
5416 hci_dev_lock(hdev);
5417
5418 if (!hdev_is_powered(hdev)) {
5419 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5420 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5421 goto unlock;
5422 }
5423
5424 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5425 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5426 &cp->addr.bdaddr);
5427 if (!conn || conn->state != BT_CONNECTED) {
5428 err = cmd_complete(sk, hdev->id,
5429 MGMT_OP_GET_CLOCK_INFO,
5430 MGMT_STATUS_NOT_CONNECTED,
5431 &rp, sizeof(rp));
5432 goto unlock;
5433 }
5434 } else {
5435 conn = NULL;
5436 }
5437
5438 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5439 if (!cmd) {
5440 err = -ENOMEM;
5441 goto unlock;
5442 }
5443
Johan Hedberg69487372014-12-05 13:36:07 +02005444 cmd->cmd_complete = clock_info_cmd_complete;
5445
Johan Hedberg95868422014-06-28 17:54:07 +03005446 hci_req_init(&req, hdev);
5447
5448 memset(&hci_cp, 0, sizeof(hci_cp));
5449 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5450
5451 if (conn) {
5452 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005453 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005454
5455 hci_cp.handle = cpu_to_le16(conn->handle);
5456 hci_cp.which = 0x01; /* Piconet clock */
5457 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5458 }
5459
5460 err = hci_req_run(&req, get_clock_info_complete);
5461 if (err < 0)
5462 mgmt_pending_remove(cmd);
5463
5464unlock:
5465 hci_dev_unlock(hdev);
5466 return err;
5467}
5468
Johan Hedberg5a154e62014-12-19 22:26:02 +02005469static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5470{
5471 struct hci_conn *conn;
5472
5473 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5474 if (!conn)
5475 return false;
5476
5477 if (conn->dst_type != type)
5478 return false;
5479
5480 if (conn->state != BT_CONNECTED)
5481 return false;
5482
5483 return true;
5484}
5485
5486/* This function requires the caller holds hdev->lock */
5487static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5488 u8 addr_type, u8 auto_connect)
5489{
5490 struct hci_dev *hdev = req->hdev;
5491 struct hci_conn_params *params;
5492
5493 params = hci_conn_params_add(hdev, addr, addr_type);
5494 if (!params)
5495 return -EIO;
5496
5497 if (params->auto_connect == auto_connect)
5498 return 0;
5499
5500 list_del_init(&params->action);
5501
5502 switch (auto_connect) {
5503 case HCI_AUTO_CONN_DISABLED:
5504 case HCI_AUTO_CONN_LINK_LOSS:
5505 __hci_update_background_scan(req);
5506 break;
5507 case HCI_AUTO_CONN_REPORT:
5508 list_add(&params->action, &hdev->pend_le_reports);
5509 __hci_update_background_scan(req);
5510 break;
5511 case HCI_AUTO_CONN_DIRECT:
5512 case HCI_AUTO_CONN_ALWAYS:
5513 if (!is_connected(hdev, addr, addr_type)) {
5514 list_add(&params->action, &hdev->pend_le_conns);
5515 __hci_update_background_scan(req);
5516 }
5517 break;
5518 }
5519
5520 params->auto_connect = auto_connect;
5521
5522 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5523 auto_connect);
5524
5525 return 0;
5526}
5527
Marcel Holtmann8afef092014-06-29 22:28:34 +02005528static void device_added(struct sock *sk, struct hci_dev *hdev,
5529 bdaddr_t *bdaddr, u8 type, u8 action)
5530{
5531 struct mgmt_ev_device_added ev;
5532
5533 bacpy(&ev.addr.bdaddr, bdaddr);
5534 ev.addr.type = type;
5535 ev.action = action;
5536
5537 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5538}
5539
Marcel Holtmann1904a852015-01-11 13:50:44 -08005540static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005541{
5542 struct pending_cmd *cmd;
5543
5544 BT_DBG("status 0x%02x", status);
5545
5546 hci_dev_lock(hdev);
5547
5548 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5549 if (!cmd)
5550 goto unlock;
5551
5552 cmd->cmd_complete(cmd, mgmt_status(status));
5553 mgmt_pending_remove(cmd);
5554
5555unlock:
5556 hci_dev_unlock(hdev);
5557}
5558
Marcel Holtmann2faade52014-06-29 19:44:03 +02005559static int add_device(struct sock *sk, struct hci_dev *hdev,
5560 void *data, u16 len)
5561{
5562 struct mgmt_cp_add_device *cp = data;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005563 struct pending_cmd *cmd;
5564 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005565 u8 auto_conn, addr_type;
5566 int err;
5567
5568 BT_DBG("%s", hdev->name);
5569
Johan Hedberg66593582014-07-09 12:59:14 +03005570 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005571 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5572 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5573 MGMT_STATUS_INVALID_PARAMS,
5574 &cp->addr, sizeof(cp->addr));
5575
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005576 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005577 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5578 MGMT_STATUS_INVALID_PARAMS,
5579 &cp->addr, sizeof(cp->addr));
5580
Johan Hedberg5a154e62014-12-19 22:26:02 +02005581 hci_req_init(&req, hdev);
5582
Marcel Holtmann2faade52014-06-29 19:44:03 +02005583 hci_dev_lock(hdev);
5584
Johan Hedberg5a154e62014-12-19 22:26:02 +02005585 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5586 if (!cmd) {
5587 err = -ENOMEM;
5588 goto unlock;
5589 }
5590
5591 cmd->cmd_complete = addr_cmd_complete;
5592
Johan Hedberg66593582014-07-09 12:59:14 +03005593 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005594 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005595 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005596 err = cmd->cmd_complete(cmd,
5597 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005598 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005599 goto unlock;
5600 }
5601
5602 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5603 cp->addr.type);
5604 if (err)
5605 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005606
Johan Hedberg5a154e62014-12-19 22:26:02 +02005607 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005608
Johan Hedberg66593582014-07-09 12:59:14 +03005609 goto added;
5610 }
5611
Marcel Holtmann2faade52014-06-29 19:44:03 +02005612 if (cp->addr.type == BDADDR_LE_PUBLIC)
5613 addr_type = ADDR_LE_DEV_PUBLIC;
5614 else
5615 addr_type = ADDR_LE_DEV_RANDOM;
5616
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005617 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005618 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005619 else if (cp->action == 0x01)
5620 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005621 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005622 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005623
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005624 /* If the connection parameters don't exist for this device,
5625 * they will be created and configured with defaults.
5626 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005627 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005628 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005629 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005630 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005631 goto unlock;
5632 }
5633
Johan Hedberg66593582014-07-09 12:59:14 +03005634added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005635 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5636
Johan Hedberg5a154e62014-12-19 22:26:02 +02005637 err = hci_req_run(&req, add_device_complete);
5638 if (err < 0) {
5639 /* ENODATA means no HCI commands were needed (e.g. if
5640 * the adapter is powered off).
5641 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005642 if (err == -ENODATA)
5643 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005644 mgmt_pending_remove(cmd);
5645 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005646
5647unlock:
5648 hci_dev_unlock(hdev);
5649 return err;
5650}
5651
Marcel Holtmann8afef092014-06-29 22:28:34 +02005652static void device_removed(struct sock *sk, struct hci_dev *hdev,
5653 bdaddr_t *bdaddr, u8 type)
5654{
5655 struct mgmt_ev_device_removed ev;
5656
5657 bacpy(&ev.addr.bdaddr, bdaddr);
5658 ev.addr.type = type;
5659
5660 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5661}
5662
Marcel Holtmann1904a852015-01-11 13:50:44 -08005663static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005664{
5665 struct pending_cmd *cmd;
5666
5667 BT_DBG("status 0x%02x", status);
5668
5669 hci_dev_lock(hdev);
5670
5671 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5672 if (!cmd)
5673 goto unlock;
5674
5675 cmd->cmd_complete(cmd, mgmt_status(status));
5676 mgmt_pending_remove(cmd);
5677
5678unlock:
5679 hci_dev_unlock(hdev);
5680}
5681
Marcel Holtmann2faade52014-06-29 19:44:03 +02005682static int remove_device(struct sock *sk, struct hci_dev *hdev,
5683 void *data, u16 len)
5684{
5685 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005686 struct pending_cmd *cmd;
5687 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005688 int err;
5689
5690 BT_DBG("%s", hdev->name);
5691
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005692 hci_req_init(&req, hdev);
5693
Marcel Holtmann2faade52014-06-29 19:44:03 +02005694 hci_dev_lock(hdev);
5695
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005696 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5697 if (!cmd) {
5698 err = -ENOMEM;
5699 goto unlock;
5700 }
5701
5702 cmd->cmd_complete = addr_cmd_complete;
5703
Marcel Holtmann2faade52014-06-29 19:44:03 +02005704 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005705 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005706 u8 addr_type;
5707
Johan Hedberg66593582014-07-09 12:59:14 +03005708 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005709 err = cmd->cmd_complete(cmd,
5710 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005711 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005712 goto unlock;
5713 }
5714
Johan Hedberg66593582014-07-09 12:59:14 +03005715 if (cp->addr.type == BDADDR_BREDR) {
5716 err = hci_bdaddr_list_del(&hdev->whitelist,
5717 &cp->addr.bdaddr,
5718 cp->addr.type);
5719 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005720 err = cmd->cmd_complete(cmd,
5721 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005722 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005723 goto unlock;
5724 }
5725
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005726 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005727
Johan Hedberg66593582014-07-09 12:59:14 +03005728 device_removed(sk, hdev, &cp->addr.bdaddr,
5729 cp->addr.type);
5730 goto complete;
5731 }
5732
Marcel Holtmann2faade52014-06-29 19:44:03 +02005733 if (cp->addr.type == BDADDR_LE_PUBLIC)
5734 addr_type = ADDR_LE_DEV_PUBLIC;
5735 else
5736 addr_type = ADDR_LE_DEV_RANDOM;
5737
Johan Hedbergc71593d2014-07-02 17:37:28 +03005738 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5739 addr_type);
5740 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005741 err = cmd->cmd_complete(cmd,
5742 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005743 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005744 goto unlock;
5745 }
5746
5747 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005748 err = cmd->cmd_complete(cmd,
5749 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005750 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005751 goto unlock;
5752 }
5753
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005754 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005755 list_del(&params->list);
5756 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005757 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005758
5759 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005760 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005761 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005762 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005763
Marcel Holtmann2faade52014-06-29 19:44:03 +02005764 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005765 err = cmd->cmd_complete(cmd,
5766 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005767 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005768 goto unlock;
5769 }
5770
Johan Hedberg66593582014-07-09 12:59:14 +03005771 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5772 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5773 list_del(&b->list);
5774 kfree(b);
5775 }
5776
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005777 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005778
Johan Hedberg19de0822014-07-06 13:06:51 +03005779 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5780 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5781 continue;
5782 device_removed(sk, hdev, &p->addr, p->addr_type);
5783 list_del(&p->action);
5784 list_del(&p->list);
5785 kfree(p);
5786 }
5787
5788 BT_DBG("All LE connection parameters were removed");
5789
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005790 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005791 }
5792
Johan Hedberg66593582014-07-09 12:59:14 +03005793complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005794 err = hci_req_run(&req, remove_device_complete);
5795 if (err < 0) {
5796 /* ENODATA means no HCI commands were needed (e.g. if
5797 * the adapter is powered off).
5798 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005799 if (err == -ENODATA)
5800 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005801 mgmt_pending_remove(cmd);
5802 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005803
5804unlock:
5805 hci_dev_unlock(hdev);
5806 return err;
5807}
5808
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005809static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5810 u16 len)
5811{
5812 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005813 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5814 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005815 u16 param_count, expected_len;
5816 int i;
5817
5818 if (!lmp_le_capable(hdev))
5819 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5820 MGMT_STATUS_NOT_SUPPORTED);
5821
5822 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005823 if (param_count > max_param_count) {
5824 BT_ERR("load_conn_param: too big param_count value %u",
5825 param_count);
5826 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5827 MGMT_STATUS_INVALID_PARAMS);
5828 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005829
5830 expected_len = sizeof(*cp) + param_count *
5831 sizeof(struct mgmt_conn_param);
5832 if (expected_len != len) {
5833 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5834 expected_len, len);
5835 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5836 MGMT_STATUS_INVALID_PARAMS);
5837 }
5838
5839 BT_DBG("%s param_count %u", hdev->name, param_count);
5840
5841 hci_dev_lock(hdev);
5842
5843 hci_conn_params_clear_disabled(hdev);
5844
5845 for (i = 0; i < param_count; i++) {
5846 struct mgmt_conn_param *param = &cp->params[i];
5847 struct hci_conn_params *hci_param;
5848 u16 min, max, latency, timeout;
5849 u8 addr_type;
5850
5851 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5852 param->addr.type);
5853
5854 if (param->addr.type == BDADDR_LE_PUBLIC) {
5855 addr_type = ADDR_LE_DEV_PUBLIC;
5856 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5857 addr_type = ADDR_LE_DEV_RANDOM;
5858 } else {
5859 BT_ERR("Ignoring invalid connection parameters");
5860 continue;
5861 }
5862
5863 min = le16_to_cpu(param->min_interval);
5864 max = le16_to_cpu(param->max_interval);
5865 latency = le16_to_cpu(param->latency);
5866 timeout = le16_to_cpu(param->timeout);
5867
5868 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5869 min, max, latency, timeout);
5870
5871 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5872 BT_ERR("Ignoring invalid connection parameters");
5873 continue;
5874 }
5875
5876 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5877 addr_type);
5878 if (!hci_param) {
5879 BT_ERR("Failed to add connection parameters");
5880 continue;
5881 }
5882
5883 hci_param->conn_min_interval = min;
5884 hci_param->conn_max_interval = max;
5885 hci_param->conn_latency = latency;
5886 hci_param->supervision_timeout = timeout;
5887 }
5888
5889 hci_dev_unlock(hdev);
5890
5891 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5892}
5893
Marcel Holtmanndbece372014-07-04 18:11:55 +02005894static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5895 void *data, u16 len)
5896{
5897 struct mgmt_cp_set_external_config *cp = data;
5898 bool changed;
5899 int err;
5900
5901 BT_DBG("%s", hdev->name);
5902
5903 if (hdev_is_powered(hdev))
5904 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5905 MGMT_STATUS_REJECTED);
5906
5907 if (cp->config != 0x00 && cp->config != 0x01)
5908 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5909 MGMT_STATUS_INVALID_PARAMS);
5910
5911 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5912 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5913 MGMT_STATUS_NOT_SUPPORTED);
5914
5915 hci_dev_lock(hdev);
5916
5917 if (cp->config)
5918 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5919 &hdev->dev_flags);
5920 else
5921 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5922 &hdev->dev_flags);
5923
5924 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5925 if (err < 0)
5926 goto unlock;
5927
5928 if (!changed)
5929 goto unlock;
5930
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005931 err = new_options(hdev, sk);
5932
Marcel Holtmanndbece372014-07-04 18:11:55 +02005933 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5934 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005935
5936 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5937 set_bit(HCI_CONFIG, &hdev->dev_flags);
5938 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5939
5940 queue_work(hdev->req_workqueue, &hdev->power_on);
5941 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005942 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005943 mgmt_index_added(hdev);
5944 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005945 }
5946
5947unlock:
5948 hci_dev_unlock(hdev);
5949 return err;
5950}
5951
Marcel Holtmann9713c172014-07-06 12:11:15 +02005952static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5953 void *data, u16 len)
5954{
5955 struct mgmt_cp_set_public_address *cp = data;
5956 bool changed;
5957 int err;
5958
5959 BT_DBG("%s", hdev->name);
5960
5961 if (hdev_is_powered(hdev))
5962 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5963 MGMT_STATUS_REJECTED);
5964
5965 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5966 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5967 MGMT_STATUS_INVALID_PARAMS);
5968
5969 if (!hdev->set_bdaddr)
5970 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5971 MGMT_STATUS_NOT_SUPPORTED);
5972
5973 hci_dev_lock(hdev);
5974
5975 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5976 bacpy(&hdev->public_addr, &cp->bdaddr);
5977
5978 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5979 if (err < 0)
5980 goto unlock;
5981
5982 if (!changed)
5983 goto unlock;
5984
5985 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5986 err = new_options(hdev, sk);
5987
5988 if (is_configured(hdev)) {
5989 mgmt_index_removed(hdev);
5990
5991 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5992
5993 set_bit(HCI_CONFIG, &hdev->dev_flags);
5994 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5995
5996 queue_work(hdev->req_workqueue, &hdev->power_on);
5997 }
5998
5999unlock:
6000 hci_dev_unlock(hdev);
6001 return err;
6002}
6003
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006004static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006005 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
6006 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006007 bool var_len;
6008 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006009} mgmt_handlers[] = {
6010 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02006011 { read_version, false, MGMT_READ_VERSION_SIZE },
6012 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
6013 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
6014 { read_controller_info, false, MGMT_READ_INFO_SIZE },
6015 { set_powered, false, MGMT_SETTING_SIZE },
6016 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
6017 { set_connectable, false, MGMT_SETTING_SIZE },
6018 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03006019 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006020 { set_link_security, false, MGMT_SETTING_SIZE },
6021 { set_ssp, false, MGMT_SETTING_SIZE },
6022 { set_hs, false, MGMT_SETTING_SIZE },
6023 { set_le, false, MGMT_SETTING_SIZE },
6024 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
6025 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
6026 { add_uuid, false, MGMT_ADD_UUID_SIZE },
6027 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
6028 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
6029 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
6030 { disconnect, false, MGMT_DISCONNECT_SIZE },
6031 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
6032 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
6033 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6034 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
6035 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
6036 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6037 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
6038 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
6039 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6040 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
6041 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
6042 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08006043 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02006044 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6045 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
6046 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
6047 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
6048 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
6049 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07006050 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03006051 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03006052 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006053 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07006054 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006055 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08006056 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02006057 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02006058 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02006059 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03006060 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02006061 { add_device, false, MGMT_ADD_DEVICE_SIZE },
6062 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006063 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
6064 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02006065 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02006066 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02006067 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01006068 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006069};
6070
Johan Hedberg03811012010-12-08 00:21:06 +02006071int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
6072{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006073 void *buf;
6074 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006075 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006076 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006077 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02006078 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02006079 int err;
6080
6081 BT_DBG("got %zu bytes", msglen);
6082
6083 if (msglen < sizeof(*hdr))
6084 return -EINVAL;
6085
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006086 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006087 if (!buf)
6088 return -ENOMEM;
6089
Al Viro6ce8e9c2014-04-06 21:25:44 -04006090 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006091 err = -EFAULT;
6092 goto done;
6093 }
6094
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006095 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006096 opcode = __le16_to_cpu(hdr->opcode);
6097 index = __le16_to_cpu(hdr->index);
6098 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006099
6100 if (len != msglen - sizeof(*hdr)) {
6101 err = -EINVAL;
6102 goto done;
6103 }
6104
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006105 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006106 hdev = hci_dev_get(index);
6107 if (!hdev) {
6108 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006109 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006110 goto done;
6111 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006112
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02006113 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006114 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02006115 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006116 err = cmd_status(sk, index, opcode,
6117 MGMT_STATUS_INVALID_INDEX);
6118 goto done;
6119 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006120
6121 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02006122 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02006123 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
6124 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006125 err = cmd_status(sk, index, opcode,
6126 MGMT_STATUS_INVALID_INDEX);
6127 goto done;
6128 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006129 }
6130
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006131 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006132 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02006133 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02006134 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006135 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006136 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02006137 }
6138
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006139 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
6140 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
6141 err = cmd_status(sk, index, opcode,
6142 MGMT_STATUS_INVALID_INDEX);
6143 goto done;
6144 }
6145
6146 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
6147 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006148 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006149 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006150 goto done;
6151 }
6152
Johan Hedbergbe22b542012-03-01 22:24:41 +02006153 handler = &mgmt_handlers[opcode];
6154
6155 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006156 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02006157 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006158 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006159 goto done;
6160 }
6161
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006162 if (hdev)
6163 mgmt_init_hdev(sk, hdev);
6164
6165 cp = buf + sizeof(*hdr);
6166
Johan Hedbergbe22b542012-03-01 22:24:41 +02006167 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006168 if (err < 0)
6169 goto done;
6170
Johan Hedberg03811012010-12-08 00:21:06 +02006171 err = msglen;
6172
6173done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006174 if (hdev)
6175 hci_dev_put(hdev);
6176
Johan Hedberg03811012010-12-08 00:21:06 +02006177 kfree(buf);
6178 return err;
6179}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006180
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006181void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006182{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006183 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006184 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006185
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006186 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6187 return;
6188
6189 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6190 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6191 else
6192 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006193}
6194
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006195void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006196{
Johan Hedberg5f159032012-03-02 03:13:19 +02006197 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006198
Marcel Holtmann1514b892013-10-06 08:25:01 -07006199 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006200 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006201
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006202 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6203 return;
6204
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006205 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006206
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02006207 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6208 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6209 else
6210 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006211}
6212
Andre Guedes6046dc32014-02-26 20:21:51 -03006213/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006214static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006215{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006216 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006217 struct hci_conn_params *p;
6218
6219 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006220 /* Needed for AUTO_OFF case where might not "really"
6221 * have been powered off.
6222 */
6223 list_del_init(&p->action);
6224
6225 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006226 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006227 case HCI_AUTO_CONN_ALWAYS:
6228 list_add(&p->action, &hdev->pend_le_conns);
6229 break;
6230 case HCI_AUTO_CONN_REPORT:
6231 list_add(&p->action, &hdev->pend_le_reports);
6232 break;
6233 default:
6234 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006235 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006236 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006237
Johan Hedberg2cf22212014-12-19 22:26:00 +02006238 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006239}
6240
Marcel Holtmann1904a852015-01-11 13:50:44 -08006241static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006242{
6243 struct cmd_lookup match = { NULL, hdev };
6244
6245 BT_DBG("status 0x%02x", status);
6246
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006247 if (!status) {
6248 /* Register the available SMP channels (BR/EDR and LE) only
6249 * when successfully powering on the controller. This late
6250 * registration is required so that LE SMP can clearly
6251 * decide if the public address or static address is used.
6252 */
6253 smp_register(hdev);
6254 }
6255
Johan Hedberg229ab392013-03-15 17:06:53 -05006256 hci_dev_lock(hdev);
6257
6258 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6259
6260 new_settings(hdev, match.sk);
6261
6262 hci_dev_unlock(hdev);
6263
6264 if (match.sk)
6265 sock_put(match.sk);
6266}
6267
Johan Hedberg70da6242013-03-15 17:06:51 -05006268static int powered_update_hci(struct hci_dev *hdev)
6269{
Johan Hedberg890ea892013-03-15 17:06:52 -05006270 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006271 u8 link_sec;
6272
Johan Hedberg890ea892013-03-15 17:06:52 -05006273 hci_req_init(&req, hdev);
6274
Johan Hedberg70da6242013-03-15 17:06:51 -05006275 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6276 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006277 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006278
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006279 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006280
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006281 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6282 u8 support = 0x01;
6283
6284 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6285 sizeof(support), &support);
6286 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006287 }
6288
Johan Hedbergc73eee92013-04-19 18:35:21 +03006289 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6290 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006291 struct hci_cp_write_le_host_supported cp;
6292
Marcel Holtmann32226e42014-07-24 20:04:16 +02006293 cp.le = 0x01;
6294 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006295
6296 /* Check first if we already have the right
6297 * host state (host features set)
6298 */
6299 if (cp.le != lmp_host_le_capable(hdev) ||
6300 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006301 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6302 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006303 }
6304
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006305 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006306 /* Make sure the controller has a good default for
6307 * advertising data. This also applies to the case
6308 * where BR/EDR was toggled during the AUTO_OFF phase.
6309 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006310 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006311 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006312 update_scan_rsp_data(&req);
6313 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006314
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006315 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6316 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006317
6318 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006319 }
6320
Johan Hedberg70da6242013-03-15 17:06:51 -05006321 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6322 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006323 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6324 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006325
6326 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006327 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006328 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006329 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006330 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006331 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006332 }
6333
Johan Hedberg229ab392013-03-15 17:06:53 -05006334 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006335}
6336
Johan Hedberg744cf192011-11-08 20:40:14 +02006337int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006338{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006339 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006340 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006341 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006342
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006343 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6344 return 0;
6345
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006346 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006347 if (powered_update_hci(hdev) == 0)
6348 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006349
Johan Hedberg229ab392013-03-15 17:06:53 -05006350 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6351 &match);
6352 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006353 }
6354
Johan Hedberg229ab392013-03-15 17:06:53 -05006355 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006356
6357 /* If the power off is because of hdev unregistration let
6358 * use the appropriate INVALID_INDEX status. Otherwise use
6359 * NOT_POWERED. We cover both scenarios here since later in
6360 * mgmt_index_removed() any hci_conn callbacks will have already
6361 * been triggered, potentially causing misleading DISCONNECTED
6362 * status responses.
6363 */
6364 if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
6365 status = MGMT_STATUS_INVALID_INDEX;
6366 else
6367 status = MGMT_STATUS_NOT_POWERED;
6368
6369 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006370
6371 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6372 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6373 zero_cod, sizeof(zero_cod), NULL);
6374
6375new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006376 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006377
6378 if (match.sk)
6379 sock_put(match.sk);
6380
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006381 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006382}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006383
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006384void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006385{
6386 struct pending_cmd *cmd;
6387 u8 status;
6388
6389 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6390 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006391 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006392
6393 if (err == -ERFKILL)
6394 status = MGMT_STATUS_RFKILLED;
6395 else
6396 status = MGMT_STATUS_FAILED;
6397
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006398 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006399
6400 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006401}
6402
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006403void mgmt_discoverable_timeout(struct hci_dev *hdev)
6404{
6405 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006406
6407 hci_dev_lock(hdev);
6408
6409 /* When discoverable timeout triggers, then just make sure
6410 * the limited discoverable flag is cleared. Even in the case
6411 * of a timeout triggered from general discoverable, it is
6412 * safe to unconditionally clear the flag.
6413 */
6414 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006415 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006416
6417 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006418 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6419 u8 scan = SCAN_PAGE;
6420 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6421 sizeof(scan), &scan);
6422 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006423 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006424 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006425 hci_req_run(&req, NULL);
6426
6427 hdev->discov_timeout = 0;
6428
Johan Hedberg9a43e252013-10-20 19:00:07 +03006429 new_settings(hdev, NULL);
6430
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006431 hci_dev_unlock(hdev);
6432}
6433
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006434void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6435 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006436{
Johan Hedberg86742e12011-11-07 23:13:38 +02006437 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006438
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006439 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006440
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006441 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006442 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006443 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006444 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006445 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006446 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006447
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006448 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006449}
Johan Hedbergf7520542011-01-20 12:34:39 +02006450
Johan Hedbergd7b25452014-05-23 13:19:53 +03006451static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6452{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006453 switch (ltk->type) {
6454 case SMP_LTK:
6455 case SMP_LTK_SLAVE:
6456 if (ltk->authenticated)
6457 return MGMT_LTK_AUTHENTICATED;
6458 return MGMT_LTK_UNAUTHENTICATED;
6459 case SMP_LTK_P256:
6460 if (ltk->authenticated)
6461 return MGMT_LTK_P256_AUTH;
6462 return MGMT_LTK_P256_UNAUTH;
6463 case SMP_LTK_P256_DEBUG:
6464 return MGMT_LTK_P256_DEBUG;
6465 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006466
6467 return MGMT_LTK_UNAUTHENTICATED;
6468}
6469
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006470void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006471{
6472 struct mgmt_ev_new_long_term_key ev;
6473
6474 memset(&ev, 0, sizeof(ev));
6475
Marcel Holtmann5192d302014-02-19 17:11:58 -08006476 /* Devices using resolvable or non-resolvable random addresses
6477 * without providing an indentity resolving key don't require
6478 * to store long term keys. Their addresses will change the
6479 * next time around.
6480 *
6481 * Only when a remote device provides an identity address
6482 * make sure the long term key is stored. If the remote
6483 * identity is known, the long term keys are internally
6484 * mapped to the identity address. So allow static random
6485 * and public addresses here.
6486 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006487 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6488 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6489 ev.store_hint = 0x00;
6490 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006491 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006492
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006493 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006494 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006495 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006496 ev.key.enc_size = key->enc_size;
6497 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006498 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006499
Johan Hedberg2ceba532014-06-16 19:25:16 +03006500 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006501 ev.key.master = 1;
6502
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006503 memcpy(ev.key.val, key->val, sizeof(key->val));
6504
Marcel Holtmann083368f2013-10-15 14:26:29 -07006505 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006506}
6507
Johan Hedberg95fbac82014-02-19 15:18:31 +02006508void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6509{
6510 struct mgmt_ev_new_irk ev;
6511
6512 memset(&ev, 0, sizeof(ev));
6513
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006514 /* For identity resolving keys from devices that are already
6515 * using a public address or static random address, do not
6516 * ask for storing this key. The identity resolving key really
6517 * is only mandatory for devices using resovlable random
6518 * addresses.
6519 *
6520 * Storing all identity resolving keys has the downside that
6521 * they will be also loaded on next boot of they system. More
6522 * identity resolving keys, means more time during scanning is
6523 * needed to actually resolve these addresses.
6524 */
6525 if (bacmp(&irk->rpa, BDADDR_ANY))
6526 ev.store_hint = 0x01;
6527 else
6528 ev.store_hint = 0x00;
6529
Johan Hedberg95fbac82014-02-19 15:18:31 +02006530 bacpy(&ev.rpa, &irk->rpa);
6531 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6532 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6533 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6534
6535 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6536}
6537
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006538void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6539 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006540{
6541 struct mgmt_ev_new_csrk ev;
6542
6543 memset(&ev, 0, sizeof(ev));
6544
6545 /* Devices using resolvable or non-resolvable random addresses
6546 * without providing an indentity resolving key don't require
6547 * to store signature resolving keys. Their addresses will change
6548 * the next time around.
6549 *
6550 * Only when a remote device provides an identity address
6551 * make sure the signature resolving key is stored. So allow
6552 * static random and public addresses here.
6553 */
6554 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6555 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6556 ev.store_hint = 0x00;
6557 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006558 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006559
6560 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6561 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6562 ev.key.master = csrk->master;
6563 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6564
6565 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6566}
6567
Andre Guedesffb5a8272014-07-01 18:10:11 -03006568void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006569 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6570 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006571{
6572 struct mgmt_ev_new_conn_param ev;
6573
Johan Hedbergc103aea2014-07-02 17:37:34 +03006574 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6575 return;
6576
Andre Guedesffb5a8272014-07-01 18:10:11 -03006577 memset(&ev, 0, sizeof(ev));
6578 bacpy(&ev.addr.bdaddr, bdaddr);
6579 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006580 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006581 ev.min_interval = cpu_to_le16(min_interval);
6582 ev.max_interval = cpu_to_le16(max_interval);
6583 ev.latency = cpu_to_le16(latency);
6584 ev.timeout = cpu_to_le16(timeout);
6585
6586 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6587}
6588
Marcel Holtmann94933992013-10-15 10:26:39 -07006589static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6590 u8 data_len)
6591{
6592 eir[eir_len++] = sizeof(type) + data_len;
6593 eir[eir_len++] = type;
6594 memcpy(&eir[eir_len], data, data_len);
6595 eir_len += data_len;
6596
6597 return eir_len;
6598}
6599
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006600void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6601 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006602{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006603 char buf[512];
6604 struct mgmt_ev_device_connected *ev = (void *) buf;
6605 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006606
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006607 bacpy(&ev->addr.bdaddr, &conn->dst);
6608 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006609
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006610 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006611
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006612 /* We must ensure that the EIR Data fields are ordered and
6613 * unique. Keep it simple for now and avoid the problem by not
6614 * adding any BR/EDR data to the LE adv.
6615 */
6616 if (conn->le_adv_data_len > 0) {
6617 memcpy(&ev->eir[eir_len],
6618 conn->le_adv_data, conn->le_adv_data_len);
6619 eir_len = conn->le_adv_data_len;
6620 } else {
6621 if (name_len > 0)
6622 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6623 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006624
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006625 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006626 eir_len = eir_append_data(ev->eir, eir_len,
6627 EIR_CLASS_OF_DEV,
6628 conn->dev_class, 3);
6629 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006630
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006631 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006632
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006633 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6634 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006635}
6636
Johan Hedberg8962ee72011-01-20 12:40:27 +02006637static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6638{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006639 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006640
Johan Hedbergf5818c22014-12-05 13:36:02 +02006641 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006642
6643 *sk = cmd->sk;
6644 sock_hold(*sk);
6645
Johan Hedberga664b5b2011-02-19 12:06:02 -03006646 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006647}
6648
Johan Hedberg124f6e32012-02-09 13:50:12 +02006649static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006650{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006651 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006652 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006653
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006654 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6655
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006656 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006657 mgmt_pending_remove(cmd);
6658}
6659
Johan Hedberg84c61d92014-08-01 11:13:30 +03006660bool mgmt_powering_down(struct hci_dev *hdev)
6661{
6662 struct pending_cmd *cmd;
6663 struct mgmt_mode *cp;
6664
6665 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6666 if (!cmd)
6667 return false;
6668
6669 cp = cmd->param;
6670 if (!cp->val)
6671 return true;
6672
6673 return false;
6674}
6675
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006676void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006677 u8 link_type, u8 addr_type, u8 reason,
6678 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006679{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006680 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006681 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006682
Johan Hedberg84c61d92014-08-01 11:13:30 +03006683 /* The connection is still in hci_conn_hash so test for 1
6684 * instead of 0 to know if this is the last one.
6685 */
6686 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6687 cancel_delayed_work(&hdev->power_off);
6688 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006689 }
6690
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006691 if (!mgmt_connected)
6692 return;
6693
Andre Guedes57eb7762013-10-30 19:01:41 -03006694 if (link_type != ACL_LINK && link_type != LE_LINK)
6695 return;
6696
Johan Hedberg744cf192011-11-08 20:40:14 +02006697 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006698
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006699 bacpy(&ev.addr.bdaddr, bdaddr);
6700 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6701 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006702
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006703 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006704
6705 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006706 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006707
Johan Hedberg124f6e32012-02-09 13:50:12 +02006708 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006709 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006710}
6711
Marcel Holtmann78929242013-10-06 23:55:47 -07006712void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6713 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006714{
Andre Guedes3655bba2013-10-30 19:01:40 -03006715 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6716 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006717 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006718
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006719 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6720 hdev);
6721
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006722 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006723 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006724 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006725
Andre Guedes3655bba2013-10-30 19:01:40 -03006726 cp = cmd->param;
6727
6728 if (bacmp(bdaddr, &cp->addr.bdaddr))
6729 return;
6730
6731 if (cp->addr.type != bdaddr_type)
6732 return;
6733
Johan Hedbergf5818c22014-12-05 13:36:02 +02006734 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006735 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006736}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006737
Marcel Holtmann445608d2013-10-06 23:55:48 -07006738void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6739 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006740{
6741 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006742
Johan Hedberg84c61d92014-08-01 11:13:30 +03006743 /* The connection is still in hci_conn_hash so test for 1
6744 * instead of 0 to know if this is the last one.
6745 */
6746 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6747 cancel_delayed_work(&hdev->power_off);
6748 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006749 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006750
Johan Hedberg4c659c32011-11-07 23:13:39 +02006751 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006752 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006753 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006754
Marcel Holtmann445608d2013-10-06 23:55:48 -07006755 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006756}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006757
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006758void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006759{
6760 struct mgmt_ev_pin_code_request ev;
6761
Johan Hedbergd8457692012-02-17 14:24:57 +02006762 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006763 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006764 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006765
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006766 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006767}
6768
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006769void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6770 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006771{
6772 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006773
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006774 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006775 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006776 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006777
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006778 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006779 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006780}
6781
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006782void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6783 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006784{
6785 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006786
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006787 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006788 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006789 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006790
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006791 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006792 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006793}
Johan Hedberga5c29682011-02-19 12:05:57 -03006794
Johan Hedberg744cf192011-11-08 20:40:14 +02006795int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006796 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006797 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006798{
6799 struct mgmt_ev_user_confirm_request ev;
6800
Johan Hedberg744cf192011-11-08 20:40:14 +02006801 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006802
Johan Hedberg272d90d2012-02-09 15:26:12 +02006803 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006804 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006805 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006806 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006807
Johan Hedberg744cf192011-11-08 20:40:14 +02006808 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006809 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006810}
6811
Johan Hedberg272d90d2012-02-09 15:26:12 +02006812int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006813 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006814{
6815 struct mgmt_ev_user_passkey_request ev;
6816
6817 BT_DBG("%s", hdev->name);
6818
Johan Hedberg272d90d2012-02-09 15:26:12 +02006819 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006820 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006821
6822 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006823 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006824}
6825
Brian Gix0df4c182011-11-16 13:53:13 -08006826static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006827 u8 link_type, u8 addr_type, u8 status,
6828 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006829{
6830 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006831
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006832 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006833 if (!cmd)
6834 return -ENOENT;
6835
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006836 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006837 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006838
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006839 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006840}
6841
Johan Hedberg744cf192011-11-08 20:40:14 +02006842int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006843 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006844{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006845 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006846 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006847}
6848
Johan Hedberg272d90d2012-02-09 15:26:12 +02006849int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006850 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006851{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006852 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006853 status,
6854 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006855}
Johan Hedberg2a611692011-02-19 12:06:00 -03006856
Brian Gix604086b2011-11-23 08:28:33 -08006857int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006858 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006859{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006860 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006861 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006862}
6863
Johan Hedberg272d90d2012-02-09 15:26:12 +02006864int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006865 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006866{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006867 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006868 status,
6869 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006870}
6871
Johan Hedberg92a25252012-09-06 18:39:26 +03006872int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6873 u8 link_type, u8 addr_type, u32 passkey,
6874 u8 entered)
6875{
6876 struct mgmt_ev_passkey_notify ev;
6877
6878 BT_DBG("%s", hdev->name);
6879
6880 bacpy(&ev.addr.bdaddr, bdaddr);
6881 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6882 ev.passkey = __cpu_to_le32(passkey);
6883 ev.entered = entered;
6884
6885 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6886}
6887
Johan Hedberge1e930f2014-09-08 17:09:49 -07006888void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006889{
6890 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006891 struct pending_cmd *cmd;
6892 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006893
Johan Hedberge1e930f2014-09-08 17:09:49 -07006894 bacpy(&ev.addr.bdaddr, &conn->dst);
6895 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6896 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006897
Johan Hedberge1e930f2014-09-08 17:09:49 -07006898 cmd = find_pairing(conn);
6899
6900 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6901 cmd ? cmd->sk : NULL);
6902
Johan Hedberga511b352014-12-11 21:45:45 +02006903 if (cmd) {
6904 cmd->cmd_complete(cmd, status);
6905 mgmt_pending_remove(cmd);
6906 }
Johan Hedberg2a611692011-02-19 12:06:00 -03006907}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006908
Marcel Holtmann464996a2013-10-15 14:26:24 -07006909void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006910{
6911 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006912 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006913
6914 if (status) {
6915 u8 mgmt_err = mgmt_status(status);
6916 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006917 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006918 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006919 }
6920
Marcel Holtmann464996a2013-10-15 14:26:24 -07006921 if (test_bit(HCI_AUTH, &hdev->flags))
6922 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6923 &hdev->dev_flags);
6924 else
6925 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6926 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006927
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006928 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006929 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006930
Johan Hedberg47990ea2012-02-22 11:58:37 +02006931 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006932 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006933
6934 if (match.sk)
6935 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006936}
6937
Johan Hedberg890ea892013-03-15 17:06:52 -05006938static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006939{
Johan Hedberg890ea892013-03-15 17:06:52 -05006940 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006941 struct hci_cp_write_eir cp;
6942
Johan Hedberg976eb202012-10-24 21:12:01 +03006943 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006944 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006945
Johan Hedbergc80da272012-02-22 15:38:48 +02006946 memset(hdev->eir, 0, sizeof(hdev->eir));
6947
Johan Hedbergcacaf522012-02-21 00:52:42 +02006948 memset(&cp, 0, sizeof(cp));
6949
Johan Hedberg890ea892013-03-15 17:06:52 -05006950 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006951}
6952
Marcel Holtmann3e248562013-10-15 14:26:25 -07006953void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006954{
6955 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006956 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006957 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006958
6959 if (status) {
6960 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006961
6962 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006963 &hdev->dev_flags)) {
6964 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006965 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006966 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006967
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006968 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6969 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006970 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006971 }
6972
6973 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006974 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006975 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006976 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6977 if (!changed)
6978 changed = test_and_clear_bit(HCI_HS_ENABLED,
6979 &hdev->dev_flags);
6980 else
6981 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006982 }
6983
6984 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6985
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006986 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006987 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006988
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006989 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006990 sock_put(match.sk);
6991
Johan Hedberg890ea892013-03-15 17:06:52 -05006992 hci_req_init(&req, hdev);
6993
Johan Hedberg37699722014-06-24 14:00:27 +03006994 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6995 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6996 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6997 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006998 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006999 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007000 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007001 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007002
7003 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007004}
7005
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08007006void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
7007{
7008 struct cmd_lookup match = { NULL, hdev };
7009 bool changed = false;
7010
7011 if (status) {
7012 u8 mgmt_err = mgmt_status(status);
7013
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08007014 if (enable) {
7015 if (test_and_clear_bit(HCI_SC_ENABLED,
7016 &hdev->dev_flags))
7017 new_settings(hdev, NULL);
7018 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
7019 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08007020
7021 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
7022 cmd_status_rsp, &mgmt_err);
7023 return;
7024 }
7025
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08007026 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08007027 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08007028 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08007029 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08007030 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
7031 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08007032
7033 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
7034 settings_rsp, &match);
7035
7036 if (changed)
7037 new_settings(hdev, match.sk);
7038
7039 if (match.sk)
7040 sock_put(match.sk);
7041}
7042
Johan Hedberg92da6092013-03-15 17:06:55 -05007043static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007044{
7045 struct cmd_lookup *match = data;
7046
Johan Hedberg90e70452012-02-23 23:09:40 +02007047 if (match->sk == NULL) {
7048 match->sk = cmd->sk;
7049 sock_hold(match->sk);
7050 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007051}
7052
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007053void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7054 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007055{
Johan Hedberg90e70452012-02-23 23:09:40 +02007056 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007057
Johan Hedberg92da6092013-03-15 17:06:55 -05007058 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7059 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7060 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007061
7062 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007063 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7064 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007065
7066 if (match.sk)
7067 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007068}
7069
Marcel Holtmann7667da32013-10-15 14:26:27 -07007070void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007071{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007072 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05007073 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007074
Johan Hedberg13928972013-03-15 17:07:00 -05007075 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007076 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007077
7078 memset(&ev, 0, sizeof(ev));
7079 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007080 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007081
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007082 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007083 if (!cmd) {
7084 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007085
Johan Hedberg13928972013-03-15 17:07:00 -05007086 /* If this is a HCI command related to powering on the
7087 * HCI dev don't send any mgmt signals.
7088 */
7089 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007090 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007091 }
7092
Marcel Holtmann7667da32013-10-15 14:26:27 -07007093 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7094 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007095}
Szymon Jancc35938b2011-03-22 13:12:21 +01007096
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007097void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007098 u8 *rand192, u8 *hash256, u8 *rand256,
7099 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007100{
7101 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007102
Johan Hedberg744cf192011-11-08 20:40:14 +02007103 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007104
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007105 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007106 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007107 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007108
7109 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007110 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7111 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007112 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03007113 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007114 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01007115
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007116 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02007117 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01007118
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007119 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007120 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007121
7122 cmd_complete(cmd->sk, hdev->id,
7123 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7124 &rp, sizeof(rp));
7125 } else {
7126 struct mgmt_rp_read_local_oob_data rp;
7127
7128 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02007129 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007130
7131 cmd_complete(cmd->sk, hdev->id,
7132 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7133 &rp, sizeof(rp));
7134 }
Szymon Jancc35938b2011-03-22 13:12:21 +01007135 }
7136
7137 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007138}
Johan Hedberge17acd42011-03-30 23:57:16 +03007139
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007140static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7141{
7142 int i;
7143
7144 for (i = 0; i < uuid_count; i++) {
7145 if (!memcmp(uuid, uuids[i], 16))
7146 return true;
7147 }
7148
7149 return false;
7150}
7151
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007152static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7153{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007154 u16 parsed = 0;
7155
7156 while (parsed < eir_len) {
7157 u8 field_len = eir[0];
7158 u8 uuid[16];
7159 int i;
7160
7161 if (field_len == 0)
7162 break;
7163
7164 if (eir_len - parsed < field_len + 1)
7165 break;
7166
7167 switch (eir[1]) {
7168 case EIR_UUID16_ALL:
7169 case EIR_UUID16_SOME:
7170 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007171 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007172 uuid[13] = eir[i + 3];
7173 uuid[12] = eir[i + 2];
7174 if (has_uuid(uuid, uuid_count, uuids))
7175 return true;
7176 }
7177 break;
7178 case EIR_UUID32_ALL:
7179 case EIR_UUID32_SOME:
7180 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007181 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007182 uuid[15] = eir[i + 5];
7183 uuid[14] = eir[i + 4];
7184 uuid[13] = eir[i + 3];
7185 uuid[12] = eir[i + 2];
7186 if (has_uuid(uuid, uuid_count, uuids))
7187 return true;
7188 }
7189 break;
7190 case EIR_UUID128_ALL:
7191 case EIR_UUID128_SOME:
7192 for (i = 0; i + 17 <= field_len; i += 16) {
7193 memcpy(uuid, eir + i + 2, 16);
7194 if (has_uuid(uuid, uuid_count, uuids))
7195 return true;
7196 }
7197 break;
7198 }
7199
7200 parsed += field_len + 1;
7201 eir += field_len + 1;
7202 }
7203
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007204 return false;
7205}
7206
Marcel Holtmann901801b2013-10-06 23:55:51 -07007207void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007208 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7209 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007210{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007211 char buf[512];
7212 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007213 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007214 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007215
Johan Hedberg75ce2082014-07-02 22:42:01 +03007216 /* Don't send events for a non-kernel initiated discovery. With
7217 * LE one exception is if we have pend_le_reports > 0 in which
7218 * case we're doing passive scanning and want these events.
7219 */
7220 if (!hci_discovery_active(hdev)) {
7221 if (link_type == ACL_LINK)
7222 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007223 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007224 return;
7225 }
Andre Guedes12602d02013-04-30 15:29:40 -03007226
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007227 /* When using service discovery with a RSSI threshold, then check
7228 * if such a RSSI threshold is specified. If a RSSI threshold has
7229 * been specified, then all results with a RSSI smaller than the
7230 * RSSI threshold will be dropped.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007231 *
7232 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7233 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007234 */
7235 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Marcel Holtmannefb25132014-12-05 13:03:34 +01007236 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007237 return;
7238
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007239 /* Make sure that the buffer is big enough. The 5 extra bytes
7240 * are for the potential CoD field.
7241 */
7242 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007243 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007244
Johan Hedberg1dc06092012-01-15 21:01:23 +02007245 memset(buf, 0, sizeof(buf));
7246
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007247 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7248 * RSSI value was reported as 0 when not available. This behavior
7249 * is kept when using device discovery. This is required for full
7250 * backwards compatibility with the API.
7251 *
7252 * However when using service discovery, the value 127 will be
7253 * returned when the RSSI is not available.
7254 */
Szymon Janc91200e92015-01-22 16:57:05 +01007255 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7256 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007257 rssi = 0;
7258
Johan Hedberg841c5642014-07-07 12:45:54 +03007259 bacpy(&ev->addr.bdaddr, bdaddr);
7260 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007261 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007262 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007263
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007264 if (eir_len > 0) {
7265 /* When using service discovery and a list of UUID is
7266 * provided, results with no matching UUID should be
7267 * dropped. In case there is a match the result is
7268 * kept and checking possible scan response data
7269 * will be skipped.
7270 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007271 if (hdev->discovery.uuid_count > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007272 match = eir_has_uuids(eir, eir_len,
7273 hdev->discovery.uuid_count,
7274 hdev->discovery.uuids);
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007275 else
7276 match = true;
7277
7278 if (!match && !scan_rsp_len)
7279 return;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007280
7281 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007282 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007283 } else {
7284 /* When using service discovery and a list of UUID is
7285 * provided, results with empty EIR or advertising data
7286 * should be dropped since they do not match any UUID.
7287 */
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007288 if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007289 return;
Marcel Holtmannea8ae252014-12-17 18:18:08 +01007290
7291 match = false;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007292 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007293
Johan Hedberg1dc06092012-01-15 21:01:23 +02007294 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7295 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007296 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007297
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007298 if (scan_rsp_len > 0) {
7299 /* When using service discovery and a list of UUID is
7300 * provided, results with no matching UUID should be
7301 * dropped if there is no previous match from the
7302 * advertising data.
7303 */
7304 if (hdev->discovery.uuid_count > 0) {
7305 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7306 hdev->discovery.uuid_count,
7307 hdev->discovery.uuids))
7308 return;
7309 }
7310
7311 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007312 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007313 } else {
7314 /* When using service discovery and a list of UUID is
7315 * provided, results with empty scan response and no
7316 * previous matched advertising data should be dropped.
7317 */
7318 if (hdev->discovery.uuid_count > 0 && !match)
7319 return;
7320 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007321
7322 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7323 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007324
Marcel Holtmann901801b2013-10-06 23:55:51 -07007325 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007326}
Johan Hedberga88a9652011-03-30 13:18:12 +03007327
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007328void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7329 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007330{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007331 struct mgmt_ev_device_found *ev;
7332 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7333 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007334
Johan Hedbergb644ba32012-01-17 21:48:47 +02007335 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007336
Johan Hedbergb644ba32012-01-17 21:48:47 +02007337 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007338
Johan Hedbergb644ba32012-01-17 21:48:47 +02007339 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007340 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007341 ev->rssi = rssi;
7342
7343 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007344 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007345
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007346 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007347
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007348 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007349}
Johan Hedberg314b2382011-04-27 10:29:57 -04007350
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007351void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007352{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007353 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007354
Andre Guedes343fb142011-11-22 17:14:19 -03007355 BT_DBG("%s discovering %u", hdev->name, discovering);
7356
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007357 memset(&ev, 0, sizeof(ev));
7358 ev.type = hdev->discovery.type;
7359 ev.discovering = discovering;
7360
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007361 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007362}
Antti Julku5e762442011-08-25 16:48:02 +03007363
Marcel Holtmann1904a852015-01-11 13:50:44 -08007364static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007365{
7366 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007367}
7368
7369void mgmt_reenable_advertising(struct hci_dev *hdev)
7370{
7371 struct hci_request req;
7372
Marcel Holtmann5976e602013-10-06 04:08:14 -07007373 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7374 return;
7375
7376 hci_req_init(&req, hdev);
7377 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007378 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007379}