blob: a91e484886feba930abbdaa6dcb520b45b375c81 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200138 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200141 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300556 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergf7b64e62010-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 Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedbergf5818c22014-12-05 13:36:02 +02001489static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
1490{
1491 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1492 cmd->param_len);
1493}
1494
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001495static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1496{
1497 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
1499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001569 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001816 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001850 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
2202 if (status) {
2203 u8 mgmt_err = mgmt_status(status);
2204
2205 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2206 &mgmt_err);
2207 return;
2208 }
2209
2210 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2211
2212 new_settings(hdev, match.sk);
2213
2214 if (match.sk)
2215 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002216
2217 /* Make sure the controller has a good default for
2218 * advertising data. Restrict the update to when LE
2219 * has actually been enabled. During power on, the
2220 * update in powered_update_hci will take care of it.
2221 */
2222 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2223 struct hci_request req;
2224
2225 hci_dev_lock(hdev);
2226
2227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002230 hci_req_run(&req, NULL);
2231
Johan Hedberga70f4b52014-07-07 15:19:50 +03002232 hci_update_background_scan(hdev);
2233
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 hci_dev_unlock(hdev);
2235 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236}
2237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239{
2240 struct mgmt_mode *cp = data;
2241 struct hci_cp_write_le_host_supported hci_cp;
2242 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002245 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_le_capable(hdev))
2250 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_INVALID_PARAMS);
2256
Johan Hedbergc73eee92013-04-19 18:35:21 +03002257 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2260 MGMT_STATUS_REJECTED);
2261
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002262 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263
2264 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002265 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002267 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 bool changed = false;
2269
2270 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2271 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2272 changed = true;
2273 }
2274
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002275 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2276 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002277 changed = true;
2278 }
2279
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2281 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283
2284 if (changed)
2285 err = new_settings(hdev, sk);
2286
Johan Hedberg1de028c2012-02-29 19:55:35 -08002287 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288 }
2289
Johan Hedberg4375f102013-09-25 13:26:10 +03002290 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2291 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002300 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002303 hci_req_init(&req, hdev);
2304
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 memset(&hci_cp, 0, sizeof(hci_cp));
2306
2307 if (val) {
2308 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002309 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002310 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 }
2314
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002315 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2316 &hci_cp);
2317
2318 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302319 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322unlock:
2323 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 return err;
2325}
2326
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002327/* This is a helper function to test for pending mgmt commands that can
2328 * cause CoD or EIR HCI commands. We can only allow one such pending
2329 * mgmt command at a time since otherwise we cannot easily track what
2330 * the current values are, will be, and based on that calculate if a new
2331 * HCI command needs to be sent and if yes with what value.
2332 */
2333static bool pending_eir_or_class(struct hci_dev *hdev)
2334{
2335 struct pending_cmd *cmd;
2336
2337 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2338 switch (cmd->opcode) {
2339 case MGMT_OP_ADD_UUID:
2340 case MGMT_OP_REMOVE_UUID:
2341 case MGMT_OP_SET_DEV_CLASS:
2342 case MGMT_OP_SET_POWERED:
2343 return true;
2344 }
2345 }
2346
2347 return false;
2348}
2349
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002350static const u8 bluetooth_base_uuid[] = {
2351 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2352 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2353};
2354
2355static u8 get_uuid_size(const u8 *uuid)
2356{
2357 u32 val;
2358
2359 if (memcmp(uuid, bluetooth_base_uuid, 12))
2360 return 128;
2361
2362 val = get_unaligned_le32(&uuid[12]);
2363 if (val > 0xffff)
2364 return 32;
2365
2366 return 16;
2367}
2368
Johan Hedberg92da6092013-03-15 17:06:55 -05002369static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2370{
2371 struct pending_cmd *cmd;
2372
2373 hci_dev_lock(hdev);
2374
2375 cmd = mgmt_pending_find(mgmt_op, hdev);
2376 if (!cmd)
2377 goto unlock;
2378
2379 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2380 hdev->dev_class, 3);
2381
2382 mgmt_pending_remove(cmd);
2383
2384unlock:
2385 hci_dev_unlock(hdev);
2386}
2387
2388static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002397 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002398 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto failed;
2411 }
2412
Andre Guedes92c4c202012-06-07 19:05:44 -03002413 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002414 if (!uuid) {
2415 err = -ENOMEM;
2416 goto failed;
2417 }
2418
2419 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002421 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedbergde66aa62013-01-27 00:31:27 +02002423 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedberg890ea892013-03-15 17:06:52 -05002425 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 update_class(&req);
2428 update_eir(&req);
2429
Johan Hedberg92da6092013-03-15 17:06:55 -05002430 err = hci_req_run(&req, add_uuid_complete);
2431 if (err < 0) {
2432 if (err != -ENODATA)
2433 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002436 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002437 goto failed;
2438 }
2439
2440 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002442 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 goto failed;
2444 }
2445
2446 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447
2448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002449 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 return err;
2451}
2452
Johan Hedberg24b78d02012-02-23 23:24:30 +02002453static bool enable_service_cache(struct hci_dev *hdev)
2454{
2455 if (!hdev_is_powered(hdev))
2456 return false;
2457
2458 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002459 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2460 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002461 return true;
2462 }
2463
2464 return false;
2465}
2466
Johan Hedberg92da6092013-03-15 17:06:55 -05002467static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2468{
2469 BT_DBG("status 0x%02x", status);
2470
2471 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2472}
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002477 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002481 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 int err, found;
2483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002484 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002488 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002491 goto unlock;
2492 }
2493
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002494 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002495 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg24b78d02012-02-23 23:24:30 +02002497 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002500 goto unlock;
2501 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002502
Johan Hedberg9246a862012-02-23 21:33:16 +02002503 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504 }
2505
2506 found = 0;
2507
Johan Hedberg056341c2013-01-27 00:31:30 +02002508 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2510 continue;
2511
2512 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002513 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 found++;
2515 }
2516
2517 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002519 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 goto unlock;
2521 }
2522
Johan Hedberg9246a862012-02-23 21:33:16 +02002523update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527 update_eir(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, remove_uuid_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 return err;
2550}
2551
Johan Hedberg92da6092013-03-15 17:06:55 -05002552static void set_class_complete(struct hci_dev *hdev, u8 status)
2553{
2554 BT_DBG("status 0x%02x", status);
2555
2556 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002561{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002562 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002563 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002564 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565 int err;
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002569 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_NOT_SUPPORTED);
2572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002574
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002575 if (pending_eir_or_class(hdev)) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_BUSY);
2578 goto unlock;
2579 }
2580
2581 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2582 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2583 MGMT_STATUS_INVALID_PARAMS);
2584 goto unlock;
2585 }
2586
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002587 hdev->major_class = cp->major;
2588 hdev->minor_class = cp->minor;
2589
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002590 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002593 goto unlock;
2594 }
2595
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 hci_req_init(&req, hdev);
2597
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002598 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002599 hci_dev_unlock(hdev);
2600 cancel_delayed_work_sync(&hdev->service_cache);
2601 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002602 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606
Johan Hedberg92da6092013-03-15 17:06:55 -05002607 err = hci_req_run(&req, set_class_complete);
2608 if (err < 0) {
2609 if (err != -ENODATA)
2610 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002613 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 goto unlock;
2615 }
2616
2617 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002618 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002619 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 goto unlock;
2621 }
2622
2623 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624
Johan Hedbergb5235a62012-02-21 14:32:24 +02002625unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627 return err;
2628}
2629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002631 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002633 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002634 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2635 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002637 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002638 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002640 BT_DBG("request for %s", hdev->name);
2641
2642 if (!lmp_bredr_capable(hdev))
2643 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2644 MGMT_STATUS_NOT_SUPPORTED);
2645
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002646 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002647 if (key_count > max_key_count) {
2648 BT_ERR("load_link_keys: too big key_count value %u",
2649 key_count);
2650 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2651 MGMT_STATUS_INVALID_PARAMS);
2652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberg86742e12011-11-07 23:13:38 +02002654 expected_len = sizeof(*cp) + key_count *
2655 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002656 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002657 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002658 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedberg4ae14302013-01-20 14:27:13 +02002663 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2664 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2665 MGMT_STATUS_INVALID_PARAMS);
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002668 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 for (i = 0; i < key_count; i++) {
2671 struct mgmt_link_key_info *key = &cp->keys[i];
2672
Marcel Holtmann8e991132014-01-10 02:07:25 -08002673 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_INVALID_PARAMS);
2676 }
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
2680 hci_link_keys_clear(hdev);
2681
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2684 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2687 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002688
2689 if (changed)
2690 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002692 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002693 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg58e92932014-06-24 14:00:26 +03002695 /* Always ignore debug keys and require a new pairing if
2696 * the user wants to use them.
2697 */
2698 if (key->type == HCI_LK_DEBUG_COMBINATION)
2699 continue;
2700
Johan Hedberg7652ff62014-06-24 13:15:49 +03002701 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2702 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 }
2704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002709 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710}
2711
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714{
2715 struct mgmt_ev_device_unpaired ev;
2716
2717 bacpy(&ev.addr.bdaddr, bdaddr);
2718 ev.addr.type = addr_type;
2719
2720 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002722}
2723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 struct mgmt_cp_unpair_device *cp = data;
2728 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 struct hci_cp_disconnect dc;
2730 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 int err;
2733
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
2739 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
2742
Johan Hedberg118da702013-01-20 14:27:20 +02002743 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2744 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2745 MGMT_STATUS_INVALID_PARAMS,
2746 &rp, sizeof(rp));
2747
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002748 hci_dev_lock(hdev);
2749
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002750 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002751 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 goto unlock;
2754 }
2755
Johan Hedberge0b2b272014-02-18 17:14:31 +02002756 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002757 /* If disconnection is requested, then look up the
2758 * connection. If the remote device is connected, it
2759 * will be later used to terminate the link.
2760 *
2761 * Setting it to NULL explicitly will cause no
2762 * termination of the link.
2763 */
2764 if (cp->disconnect)
2765 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2766 &cp->addr.bdaddr);
2767 else
2768 conn = NULL;
2769
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 } else {
2772 u8 addr_type;
2773
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002774 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2775 &cp->addr.bdaddr);
2776 if (conn) {
2777 /* Defer clearing up the connection parameters
2778 * until closing to give a chance of keeping
2779 * them if a repairing happens.
2780 */
2781 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2782
2783 /* If disconnection is not requested, then
2784 * clear the connection variable so that the
2785 * link is not terminated.
2786 */
2787 if (!cp->disconnect)
2788 conn = NULL;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_LE_PUBLIC)
2792 addr_type = ADDR_LE_DEV_PUBLIC;
2793 else
2794 addr_type = ADDR_LE_DEV_RANDOM;
2795
Johan Hedberga7ec7332014-02-18 17:14:35 +02002796 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2797
Johan Hedberge0b2b272014-02-18 17:14:31 +02002798 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2799 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002802 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002803 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 goto unlock;
2805 }
2806
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002807 /* If the connection variable is set, then termination of the
2808 * link is requested.
2809 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002810 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002813 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 }
2816
Johan Hedberg124f6e32012-02-09 13:50:12 +02002817 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 if (!cmd) {
2820 err = -ENOMEM;
2821 goto unlock;
2822 }
2823
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002824 cmd->cmd_complete = addr_cmd_complete;
2825
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002826 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002827 dc.reason = 0x13; /* Remote User Terminated Connection */
2828 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2829 if (err < 0)
2830 mgmt_pending_remove(cmd);
2831
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002833 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002834 return err;
2835}
2836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002837static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002839{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002840 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002841 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002842 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002843 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844 int err;
2845
2846 BT_DBG("");
2847
Johan Hedberg06a63b12013-01-20 14:27:21 +02002848 memset(&rp, 0, sizeof(rp));
2849 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2850 rp.addr.type = cp->addr.type;
2851
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002852 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002853 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2854 MGMT_STATUS_INVALID_PARAMS,
2855 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002856
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002857 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002858
2859 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002860 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2861 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002862 goto failed;
2863 }
2864
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002865 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002866 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2867 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002868 goto failed;
2869 }
2870
Andre Guedes591f47f2012-04-24 21:02:49 -03002871 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002872 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2873 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002874 else
2875 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002876
Vishal Agarwalf9607272012-06-13 05:32:43 +05302877 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002878 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2879 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 goto failed;
2881 }
2882
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002883 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002884 if (!cmd) {
2885 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002887 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002888
Johan Hedbergf5818c22014-12-05 13:36:02 +02002889 cmd->cmd_complete = generic_cmd_complete;
2890
Johan Hedberge3f2f922014-08-18 20:33:33 +03002891 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002893 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894
2895failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002897 return err;
2898}
2899
Andre Guedes57c14772012-04-24 21:02:50 -03002900static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002901{
2902 switch (link_type) {
2903 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002904 switch (addr_type) {
2905 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002906 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002907
Johan Hedberg48264f02011-11-09 13:58:58 +02002908 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002909 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002910 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002911 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002912
Johan Hedberg4c659c32011-11-07 23:13:39 +02002913 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002914 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002915 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002916 }
2917}
2918
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002919static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2920 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002921{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002922 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002923 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002924 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002925 int err;
2926 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002927
2928 BT_DBG("");
2929
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002930 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002931
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002935 goto unlock;
2936 }
2937
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002938 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002939 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2940 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002941 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002942 }
2943
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002944 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002945 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002946 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002947 err = -ENOMEM;
2948 goto unlock;
2949 }
2950
Johan Hedberg2784eb42011-01-21 13:56:35 +02002951 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002952 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002953 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2954 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002955 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002956 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002957 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002958 continue;
2959 i++;
2960 }
2961
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002962 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002963
Johan Hedberg4c659c32011-11-07 23:13:39 +02002964 /* Recalculate length in case of filtered SCO connections, etc */
2965 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002969
Johan Hedberga38528f2011-01-22 06:46:43 +02002970 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002971
2972unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002973 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002974 return err;
2975}
2976
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002979{
2980 struct pending_cmd *cmd;
2981 int err;
2982
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002983 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002985 if (!cmd)
2986 return -ENOMEM;
2987
Johan Hedbergd8457692012-02-17 14:24:57 +02002988 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002990 if (err < 0)
2991 mgmt_pending_remove(cmd);
2992
2993 return err;
2994}
2995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002996static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002998{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002999 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003000 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003001 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003002 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003003 int err;
3004
3005 BT_DBG("");
3006
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003007 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003008
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003009 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003010 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003011 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012 goto failed;
3013 }
3014
Johan Hedbergd8457692012-02-17 14:24:57 +02003015 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003016 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003017 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003018 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003019 goto failed;
3020 }
3021
3022 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003023 struct mgmt_cp_pin_code_neg_reply ncp;
3024
3025 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003026
3027 BT_ERR("PIN code is not 16 bytes long");
3028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003033
3034 goto failed;
3035 }
3036
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003037 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003038 if (!cmd) {
3039 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003041 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003043 cmd->cmd_complete = addr_cmd_complete;
3044
Johan Hedbergd8457692012-02-17 14:24:57 +02003045 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003047 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003048
3049 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3050 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003051 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003052
3053failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003054 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003055 return err;
3056}
3057
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003058static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3059 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003061 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003062
3063 BT_DBG("");
3064
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003065 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3066 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3067 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3068
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003069 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003070
3071 hdev->io_capability = cp->io_capability;
3072
3073 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003074 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003076 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003077
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003078 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3079 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003080}
3081
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003082static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003083{
3084 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003085 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003087 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003088 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3089 continue;
3090
Johan Hedberge9a416b2011-02-19 12:05:56 -03003091 if (cmd->user_data != conn)
3092 continue;
3093
3094 return cmd;
3095 }
3096
3097 return NULL;
3098}
3099
3100static void pairing_complete(struct pending_cmd *cmd, u8 status)
3101{
3102 struct mgmt_rp_pair_device rp;
3103 struct hci_conn *conn = cmd->user_data;
3104
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003105 bacpy(&rp.addr.bdaddr, &conn->dst);
3106 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003107
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003108 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003109 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003110
3111 /* So we don't get further callbacks for this connection */
3112 conn->connect_cfm_cb = NULL;
3113 conn->security_cfm_cb = NULL;
3114 conn->disconn_cfm_cb = NULL;
3115
David Herrmann76a68ba2013-04-06 20:28:37 +02003116 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003117 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003118
Johan Hedberga664b5b2011-02-19 12:06:02 -03003119 mgmt_pending_remove(cmd);
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 Hedberge9a416b2011-02-19 12:05:56 -03003125}
3126
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003127void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3128{
3129 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3130 struct pending_cmd *cmd;
3131
3132 cmd = find_pairing(conn);
3133 if (cmd)
Johan Hedberg04ab2742014-12-05 13:36:04 +02003134 cmd->cmd_complete(cmd, status);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003135}
3136
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3138{
3139 struct pending_cmd *cmd;
3140
3141 BT_DBG("status %u", status);
3142
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003143 cmd = find_pairing(conn);
3144 if (!cmd)
3145 BT_DBG("Unable to find a pending command");
3146 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003147 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148}
3149
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003150static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303151{
3152 struct pending_cmd *cmd;
3153
3154 BT_DBG("status %u", status);
3155
3156 if (!status)
3157 return;
3158
3159 cmd = find_pairing(conn);
3160 if (!cmd)
3161 BT_DBG("Unable to find a pending command");
3162 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003163 cmd->cmd_complete(cmd, mgmt_status(status));
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303164}
3165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003166static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003168{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003169 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003170 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003171 struct pending_cmd *cmd;
3172 u8 sec_level, auth_type;
3173 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003174 int err;
3175
3176 BT_DBG("");
3177
Szymon Jancf950a30e2013-01-18 12:48:07 +01003178 memset(&rp, 0, sizeof(rp));
3179 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3180 rp.addr.type = cp->addr.type;
3181
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003182 if (!bdaddr_type_is_valid(cp->addr.type))
3183 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3184 MGMT_STATUS_INVALID_PARAMS,
3185 &rp, sizeof(rp));
3186
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003187 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3188 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3189 MGMT_STATUS_INVALID_PARAMS,
3190 &rp, sizeof(rp));
3191
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003192 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003193
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003194 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003195 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3196 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003197 goto unlock;
3198 }
3199
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003200 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003201 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003202
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003203 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003204 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3205 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003206 } else {
3207 u8 addr_type;
3208
3209 /* Convert from L2CAP channel address type to HCI address type
3210 */
3211 if (cp->addr.type == BDADDR_LE_PUBLIC)
3212 addr_type = ADDR_LE_DEV_PUBLIC;
3213 else
3214 addr_type = ADDR_LE_DEV_RANDOM;
3215
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003216 /* When pairing a new device, it is expected to remember
3217 * this device for future connections. Adding the connection
3218 * parameter information ahead of time allows tracking
3219 * of the slave preferred values and will speed up any
3220 * further connection establishment.
3221 *
3222 * If connection parameters already exist, then they
3223 * will be kept and this function does nothing.
3224 */
3225 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3226
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003227 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003228 sec_level, HCI_LE_CONN_TIMEOUT,
3229 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003230 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003231
Ville Tervo30e76272011-02-22 16:10:53 -03003232 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003233 int status;
3234
3235 if (PTR_ERR(conn) == -EBUSY)
3236 status = MGMT_STATUS_BUSY;
3237 else
3238 status = MGMT_STATUS_CONNECT_FAILED;
3239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003240 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003241 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003242 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243 goto unlock;
3244 }
3245
3246 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003247 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003248 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003249 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003250 goto unlock;
3251 }
3252
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003253 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003254 if (!cmd) {
3255 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003256 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003257 goto unlock;
3258 }
3259
Johan Hedberg04ab2742014-12-05 13:36:04 +02003260 cmd->cmd_complete = pairing_complete;
3261
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003262 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003263 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003264 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003265 conn->security_cfm_cb = pairing_complete_cb;
3266 conn->disconn_cfm_cb = pairing_complete_cb;
3267 } else {
3268 conn->connect_cfm_cb = le_pairing_complete_cb;
3269 conn->security_cfm_cb = le_pairing_complete_cb;
3270 conn->disconn_cfm_cb = le_pairing_complete_cb;
3271 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003272
Johan Hedberge9a416b2011-02-19 12:05:56 -03003273 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003274 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003275
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003276 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003277 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003278 pairing_complete(cmd, 0);
3279
3280 err = 0;
3281
3282unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003283 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284 return err;
3285}
3286
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003287static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3288 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003289{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003290 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003291 struct pending_cmd *cmd;
3292 struct hci_conn *conn;
3293 int err;
3294
3295 BT_DBG("");
3296
Johan Hedberg28424702012-02-02 04:02:29 +02003297 hci_dev_lock(hdev);
3298
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003299 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003300 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003302 goto unlock;
3303 }
3304
Johan Hedberg28424702012-02-02 04:02:29 +02003305 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3306 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003307 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003308 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003309 goto unlock;
3310 }
3311
3312 conn = cmd->user_data;
3313
3314 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003315 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003316 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003317 goto unlock;
3318 }
3319
3320 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003322 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003323 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003324unlock:
3325 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003326 return err;
3327}
3328
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003329static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003330 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003332{
Johan Hedberga5c29682011-02-19 12:05:57 -03003333 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003334 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003335 int err;
3336
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003337 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003338
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003339 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003340 err = cmd_complete(sk, hdev->id, mgmt_op,
3341 MGMT_STATUS_NOT_POWERED, addr,
3342 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003343 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003344 }
3345
Johan Hedberg1707c602013-03-15 17:07:15 -05003346 if (addr->type == BDADDR_BREDR)
3347 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003348 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003349 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003350
Johan Hedberg272d90d2012-02-09 15:26:12 +02003351 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003352 err = cmd_complete(sk, hdev->id, mgmt_op,
3353 MGMT_STATUS_NOT_CONNECTED, addr,
3354 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003355 goto done;
3356 }
3357
Johan Hedberg1707c602013-03-15 17:07:15 -05003358 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003359 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003360 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003361 err = cmd_complete(sk, hdev->id, mgmt_op,
3362 MGMT_STATUS_SUCCESS, addr,
3363 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003364 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003365 err = cmd_complete(sk, hdev->id, mgmt_op,
3366 MGMT_STATUS_FAILED, addr,
3367 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003368
Brian Gix47c15e22011-11-16 13:53:14 -08003369 goto done;
3370 }
3371
Johan Hedberg1707c602013-03-15 17:07:15 -05003372 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003373 if (!cmd) {
3374 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003375 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003376 }
3377
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003378 cmd->cmd_complete = addr_cmd_complete;
3379
Brian Gix0df4c182011-11-16 13:53:13 -08003380 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003381 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3382 struct hci_cp_user_passkey_reply cp;
3383
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003385 cp.passkey = passkey;
3386 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3387 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003388 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3389 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003390
Johan Hedberga664b5b2011-02-19 12:06:02 -03003391 if (err < 0)
3392 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003393
Brian Gix0df4c182011-11-16 13:53:13 -08003394done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003395 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003396 return err;
3397}
3398
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303399static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3400 void *data, u16 len)
3401{
3402 struct mgmt_cp_pin_code_neg_reply *cp = data;
3403
3404 BT_DBG("");
3405
Johan Hedberg1707c602013-03-15 17:07:15 -05003406 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303407 MGMT_OP_PIN_CODE_NEG_REPLY,
3408 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3409}
3410
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003411static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3412 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003413{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003414 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003415
3416 BT_DBG("");
3417
3418 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003419 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003421
Johan Hedberg1707c602013-03-15 17:07:15 -05003422 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003423 MGMT_OP_USER_CONFIRM_REPLY,
3424 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003425}
3426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003427static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003428 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003429{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003430 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003431
3432 BT_DBG("");
3433
Johan Hedberg1707c602013-03-15 17:07:15 -05003434 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003435 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3436 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003437}
3438
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3440 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003441{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003442 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003443
3444 BT_DBG("");
3445
Johan Hedberg1707c602013-03-15 17:07:15 -05003446 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003447 MGMT_OP_USER_PASSKEY_REPLY,
3448 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003449}
3450
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003451static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003452 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003453{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003454 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003455
3456 BT_DBG("");
3457
Johan Hedberg1707c602013-03-15 17:07:15 -05003458 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003459 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3460 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003461}
3462
Johan Hedberg13928972013-03-15 17:07:00 -05003463static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003464{
Johan Hedberg13928972013-03-15 17:07:00 -05003465 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003466 struct hci_cp_write_local_name cp;
3467
Johan Hedberg13928972013-03-15 17:07:00 -05003468 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003469
Johan Hedberg890ea892013-03-15 17:06:52 -05003470 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003471}
3472
Johan Hedberg13928972013-03-15 17:07:00 -05003473static void set_name_complete(struct hci_dev *hdev, u8 status)
3474{
3475 struct mgmt_cp_set_local_name *cp;
3476 struct pending_cmd *cmd;
3477
3478 BT_DBG("status 0x%02x", status);
3479
3480 hci_dev_lock(hdev);
3481
3482 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3483 if (!cmd)
3484 goto unlock;
3485
3486 cp = cmd->param;
3487
3488 if (status)
3489 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3490 mgmt_status(status));
3491 else
3492 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3493 cp, sizeof(*cp));
3494
3495 mgmt_pending_remove(cmd);
3496
3497unlock:
3498 hci_dev_unlock(hdev);
3499}
3500
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003501static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003503{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003504 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003505 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003506 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003507 int err;
3508
3509 BT_DBG("");
3510
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003511 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003512
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003513 /* If the old values are the same as the new ones just return a
3514 * direct command complete event.
3515 */
3516 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3517 !memcmp(hdev->short_name, cp->short_name,
3518 sizeof(hdev->short_name))) {
3519 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3520 data, len);
3521 goto failed;
3522 }
3523
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003524 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003525
Johan Hedbergb5235a62012-02-21 14:32:24 +02003526 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003528
3529 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003530 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003531 if (err < 0)
3532 goto failed;
3533
3534 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003535 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003536
Johan Hedbergb5235a62012-02-21 14:32:24 +02003537 goto failed;
3538 }
3539
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003540 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003541 if (!cmd) {
3542 err = -ENOMEM;
3543 goto failed;
3544 }
3545
Johan Hedberg13928972013-03-15 17:07:00 -05003546 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3547
Johan Hedberg890ea892013-03-15 17:06:52 -05003548 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003549
3550 if (lmp_bredr_capable(hdev)) {
3551 update_name(&req);
3552 update_eir(&req);
3553 }
3554
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003555 /* The name is stored in the scan response data and so
3556 * no need to udpate the advertising data here.
3557 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003558 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003559 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003560
Johan Hedberg13928972013-03-15 17:07:00 -05003561 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003562 if (err < 0)
3563 mgmt_pending_remove(cmd);
3564
3565failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003566 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003567 return err;
3568}
3569
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003570static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003571 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003572{
Szymon Jancc35938b2011-03-22 13:12:21 +01003573 struct pending_cmd *cmd;
3574 int err;
3575
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003576 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003577
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003578 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003579
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003580 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003582 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003583 goto unlock;
3584 }
3585
Andre Guedes9a1a1992012-07-24 15:03:48 -03003586 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003587 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003588 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003589 goto unlock;
3590 }
3591
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003592 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003593 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003594 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003595 goto unlock;
3596 }
3597
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003598 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003599 if (!cmd) {
3600 err = -ENOMEM;
3601 goto unlock;
3602 }
3603
Johan Hedberg710f11c2014-05-26 11:21:22 +03003604 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003605 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3606 0, NULL);
3607 else
3608 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3609
Szymon Jancc35938b2011-03-22 13:12:21 +01003610 if (err < 0)
3611 mgmt_pending_remove(cmd);
3612
3613unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003614 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003615 return err;
3616}
3617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003618static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003619 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003620{
Szymon Janc2763eda2011-03-22 13:12:22 +01003621 int err;
3622
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003623 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003624
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003625 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003626
Marcel Holtmannec109112014-01-10 02:07:30 -08003627 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3628 struct mgmt_cp_add_remote_oob_data *cp = data;
3629 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003630
Johan Hedbergc19a4952014-11-17 20:52:19 +02003631 if (cp->addr.type != BDADDR_BREDR) {
3632 err = cmd_complete(sk, hdev->id,
3633 MGMT_OP_ADD_REMOTE_OOB_DATA,
3634 MGMT_STATUS_INVALID_PARAMS,
3635 &cp->addr, sizeof(cp->addr));
3636 goto unlock;
3637 }
3638
Marcel Holtmannec109112014-01-10 02:07:30 -08003639 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003640 cp->addr.type, cp->hash,
3641 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003642 if (err < 0)
3643 status = MGMT_STATUS_FAILED;
3644 else
3645 status = MGMT_STATUS_SUCCESS;
3646
3647 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3648 status, &cp->addr, sizeof(cp->addr));
3649 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3650 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003651 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003652 u8 status;
3653
Johan Hedbergc19a4952014-11-17 20:52:19 +02003654 if (cp->addr.type != BDADDR_BREDR) {
3655 err = cmd_complete(sk, hdev->id,
3656 MGMT_OP_ADD_REMOTE_OOB_DATA,
3657 MGMT_STATUS_INVALID_PARAMS,
3658 &cp->addr, sizeof(cp->addr));
3659 goto unlock;
3660 }
3661
Johan Hedberg86df9202014-10-26 20:52:27 +01003662 if (bdaddr_type_is_le(cp->addr.type)) {
3663 rand192 = NULL;
3664 hash192 = NULL;
3665 } else {
3666 rand192 = cp->rand192;
3667 hash192 = cp->hash192;
3668 }
3669
Johan Hedberg81328d52014-10-26 20:33:47 +01003670 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003671 cp->addr.type, hash192, rand192,
3672 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003673 if (err < 0)
3674 status = MGMT_STATUS_FAILED;
3675 else
3676 status = MGMT_STATUS_SUCCESS;
3677
3678 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3679 status, &cp->addr, sizeof(cp->addr));
3680 } else {
3681 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3682 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3683 MGMT_STATUS_INVALID_PARAMS);
3684 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003685
Johan Hedbergc19a4952014-11-17 20:52:19 +02003686unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003687 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003688 return err;
3689}
3690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003691static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003692 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003693{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003694 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003695 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003696 int err;
3697
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003698 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003699
Johan Hedbergc19a4952014-11-17 20:52:19 +02003700 if (cp->addr.type != BDADDR_BREDR)
3701 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3702 MGMT_STATUS_INVALID_PARAMS,
3703 &cp->addr, sizeof(cp->addr));
3704
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003705 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003706
Johan Hedbergeedbd582014-11-15 09:34:23 +02003707 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3708 hci_remote_oob_data_clear(hdev);
3709 status = MGMT_STATUS_SUCCESS;
3710 goto done;
3711 }
3712
Johan Hedberg6928a922014-10-26 20:46:09 +01003713 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003714 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003715 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003716 else
Szymon Janca6785be2012-12-13 15:11:21 +01003717 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003718
Johan Hedbergeedbd582014-11-15 09:34:23 +02003719done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003720 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003721 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003722
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003723 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003724 return err;
3725}
3726
Marcel Holtmann80190442014-12-04 11:36:36 +01003727static bool trigger_discovery(struct hci_request *req, u8 *status)
3728{
3729 struct hci_dev *hdev = req->hdev;
3730 struct hci_cp_le_set_scan_param param_cp;
3731 struct hci_cp_le_set_scan_enable enable_cp;
3732 struct hci_cp_inquiry inq_cp;
3733 /* General inquiry access code (GIAC) */
3734 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3735 u8 own_addr_type;
3736 int err;
3737
3738 switch (hdev->discovery.type) {
3739 case DISCOV_TYPE_BREDR:
3740 *status = mgmt_bredr_support(hdev);
3741 if (*status)
3742 return false;
3743
3744 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3745 *status = MGMT_STATUS_BUSY;
3746 return false;
3747 }
3748
3749 hci_inquiry_cache_flush(hdev);
3750
3751 memset(&inq_cp, 0, sizeof(inq_cp));
3752 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3753 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3754 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3755 break;
3756
3757 case DISCOV_TYPE_LE:
3758 case DISCOV_TYPE_INTERLEAVED:
3759 *status = mgmt_le_support(hdev);
3760 if (*status)
3761 return false;
3762
3763 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3764 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3765 *status = MGMT_STATUS_NOT_SUPPORTED;
3766 return false;
3767 }
3768
3769 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3770 /* Don't let discovery abort an outgoing
3771 * connection attempt that's using directed
3772 * advertising.
3773 */
3774 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3775 BT_CONNECT)) {
3776 *status = MGMT_STATUS_REJECTED;
3777 return false;
3778 }
3779
3780 disable_advertising(req);
3781 }
3782
3783 /* If controller is scanning, it means the background scanning
3784 * is running. Thus, we should temporarily stop it in order to
3785 * set the discovery scanning parameters.
3786 */
3787 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3788 hci_req_add_le_scan_disable(req);
3789
3790 memset(&param_cp, 0, sizeof(param_cp));
3791
3792 /* All active scans will be done with either a resolvable
3793 * private address (when privacy feature has been enabled)
3794 * or unresolvable private address.
3795 */
3796 err = hci_update_random_address(req, true, &own_addr_type);
3797 if (err < 0) {
3798 *status = MGMT_STATUS_FAILED;
3799 return false;
3800 }
3801
3802 param_cp.type = LE_SCAN_ACTIVE;
3803 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3804 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3805 param_cp.own_address_type = own_addr_type;
3806 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3807 &param_cp);
3808
3809 memset(&enable_cp, 0, sizeof(enable_cp));
3810 enable_cp.enable = LE_SCAN_ENABLE;
3811 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3812 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3813 &enable_cp);
3814 break;
3815
3816 default:
3817 *status = MGMT_STATUS_INVALID_PARAMS;
3818 return false;
3819 }
3820
3821 return true;
3822}
3823
Andre Guedes7c307722013-04-30 15:29:28 -03003824static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3825{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003826 struct pending_cmd *cmd;
3827 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003828
Andre Guedes7c307722013-04-30 15:29:28 -03003829 BT_DBG("status %d", status);
3830
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003831 hci_dev_lock(hdev);
3832
3833 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003834 if (!cmd)
3835 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3836
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003837 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003838 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003839 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003840 }
3841
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003842 if (status) {
3843 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3844 goto unlock;
3845 }
3846
Andre Guedes7c307722013-04-30 15:29:28 -03003847 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003848
3849 switch (hdev->discovery.type) {
3850 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003851 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003852 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003853 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003854 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003855 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003856 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003857 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003858 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003859 default:
3860 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003861 timeout = 0;
3862 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003863 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003864
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003865 if (timeout)
3866 queue_delayed_work(hdev->workqueue,
3867 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003868
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003869unlock:
3870 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003871}
3872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003873static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003874 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003875{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003876 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003877 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003878 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003879 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003880 int err;
3881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003882 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003883
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003884 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003885
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003886 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003887 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3888 MGMT_STATUS_NOT_POWERED,
3889 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003890 goto failed;
3891 }
3892
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003893 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3894 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003895 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3896 MGMT_STATUS_BUSY, &cp->type,
3897 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003898 goto failed;
3899 }
3900
Johan Hedberg2922a942014-12-05 13:36:06 +02003901 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003902 if (!cmd) {
3903 err = -ENOMEM;
3904 goto failed;
3905 }
3906
Johan Hedberg2922a942014-12-05 13:36:06 +02003907 cmd->cmd_complete = generic_cmd_complete;
3908
Marcel Holtmann22078802014-12-05 11:45:22 +01003909 /* Clear the discovery filter first to free any previously
3910 * allocated memory for the UUID list.
3911 */
3912 hci_discovery_filter_clear(hdev);
3913
Andre Guedes4aab14e2012-02-17 20:39:36 -03003914 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003915 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003916
Andre Guedes7c307722013-04-30 15:29:28 -03003917 hci_req_init(&req, hdev);
3918
Marcel Holtmann80190442014-12-04 11:36:36 +01003919 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003920 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003921 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003922 mgmt_pending_remove(cmd);
3923 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003924 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003925
Andre Guedes7c307722013-04-30 15:29:28 -03003926 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003927 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003928 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003929 goto failed;
3930 }
3931
3932 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003933
3934failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003935 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003936 return err;
3937}
3938
Johan Hedberg2922a942014-12-05 13:36:06 +02003939static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
3940{
3941 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
3942}
3943
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003944static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3945 void *data, u16 len)
3946{
3947 struct mgmt_cp_start_service_discovery *cp = data;
3948 struct pending_cmd *cmd;
3949 struct hci_request req;
3950 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3951 u16 uuid_count, expected_len;
3952 u8 status;
3953 int err;
3954
3955 BT_DBG("%s", hdev->name);
3956
3957 hci_dev_lock(hdev);
3958
3959 if (!hdev_is_powered(hdev)) {
3960 err = cmd_complete(sk, hdev->id,
3961 MGMT_OP_START_SERVICE_DISCOVERY,
3962 MGMT_STATUS_NOT_POWERED,
3963 &cp->type, sizeof(cp->type));
3964 goto failed;
3965 }
3966
3967 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3968 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3969 err = cmd_complete(sk, hdev->id,
3970 MGMT_OP_START_SERVICE_DISCOVERY,
3971 MGMT_STATUS_BUSY, &cp->type,
3972 sizeof(cp->type));
3973 goto failed;
3974 }
3975
3976 uuid_count = __le16_to_cpu(cp->uuid_count);
3977 if (uuid_count > max_uuid_count) {
3978 BT_ERR("service_discovery: too big uuid_count value %u",
3979 uuid_count);
3980 err = cmd_complete(sk, hdev->id,
3981 MGMT_OP_START_SERVICE_DISCOVERY,
3982 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3983 sizeof(cp->type));
3984 goto failed;
3985 }
3986
3987 expected_len = sizeof(*cp) + uuid_count * 16;
3988 if (expected_len != len) {
3989 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3990 expected_len, len);
3991 err = cmd_complete(sk, hdev->id,
3992 MGMT_OP_START_SERVICE_DISCOVERY,
3993 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3994 sizeof(cp->type));
3995 goto failed;
3996 }
3997
3998 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02003999 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004000 if (!cmd) {
4001 err = -ENOMEM;
4002 goto failed;
4003 }
4004
Johan Hedberg2922a942014-12-05 13:36:06 +02004005 cmd->cmd_complete = service_discovery_cmd_complete;
4006
Marcel Holtmann22078802014-12-05 11:45:22 +01004007 /* Clear the discovery filter first to free any previously
4008 * allocated memory for the UUID list.
4009 */
4010 hci_discovery_filter_clear(hdev);
4011
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004012 hdev->discovery.type = cp->type;
4013 hdev->discovery.rssi = cp->rssi;
4014 hdev->discovery.uuid_count = uuid_count;
4015
4016 if (uuid_count > 0) {
4017 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4018 GFP_KERNEL);
4019 if (!hdev->discovery.uuids) {
4020 err = cmd_complete(sk, hdev->id,
4021 MGMT_OP_START_SERVICE_DISCOVERY,
4022 MGMT_STATUS_FAILED,
4023 &cp->type, sizeof(cp->type));
4024 mgmt_pending_remove(cmd);
4025 goto failed;
4026 }
4027 }
4028
4029 hci_req_init(&req, hdev);
4030
4031 if (!trigger_discovery(&req, &status)) {
4032 err = cmd_complete(sk, hdev->id,
4033 MGMT_OP_START_SERVICE_DISCOVERY,
4034 status, &cp->type, sizeof(cp->type));
4035 mgmt_pending_remove(cmd);
4036 goto failed;
4037 }
4038
4039 err = hci_req_run(&req, start_discovery_complete);
4040 if (err < 0) {
4041 mgmt_pending_remove(cmd);
4042 goto failed;
4043 }
4044
4045 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4046
4047failed:
4048 hci_dev_unlock(hdev);
4049 return err;
4050}
4051
Andre Guedes0e05bba2013-04-30 15:29:33 -03004052static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4053{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004054 struct pending_cmd *cmd;
4055
Andre Guedes0e05bba2013-04-30 15:29:33 -03004056 BT_DBG("status %d", status);
4057
4058 hci_dev_lock(hdev);
4059
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004060 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4061 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004062 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004063 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004064 }
4065
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004066 if (!status)
4067 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004068
Andre Guedes0e05bba2013-04-30 15:29:33 -03004069 hci_dev_unlock(hdev);
4070}
4071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004072static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004073 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004074{
Johan Hedbergd9306502012-02-20 23:25:18 +02004075 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004076 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004077 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004078 int err;
4079
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004080 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004081
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004082 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004083
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004084 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004085 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004086 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4087 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004088 goto unlock;
4089 }
4090
4091 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004092 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004093 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4094 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004095 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004096 }
4097
Johan Hedberg2922a942014-12-05 13:36:06 +02004098 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004099 if (!cmd) {
4100 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004101 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004102 }
4103
Johan Hedberg2922a942014-12-05 13:36:06 +02004104 cmd->cmd_complete = generic_cmd_complete;
4105
Andre Guedes0e05bba2013-04-30 15:29:33 -03004106 hci_req_init(&req, hdev);
4107
Johan Hedberg21a60d32014-06-10 14:05:58 +03004108 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004109
Johan Hedberg21a60d32014-06-10 14:05:58 +03004110 err = hci_req_run(&req, stop_discovery_complete);
4111 if (!err) {
4112 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004113 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004114 }
4115
Johan Hedberg21a60d32014-06-10 14:05:58 +03004116 mgmt_pending_remove(cmd);
4117
4118 /* If no HCI commands were sent we're done */
4119 if (err == -ENODATA) {
4120 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4121 &mgmt_cp->type, sizeof(mgmt_cp->type));
4122 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4123 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004124
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004125unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004126 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004127 return err;
4128}
4129
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004130static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004131 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004132{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004133 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004134 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004135 int err;
4136
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004137 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004138
Johan Hedberg561aafb2012-01-04 13:31:59 +02004139 hci_dev_lock(hdev);
4140
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004141 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004142 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4143 MGMT_STATUS_FAILED, &cp->addr,
4144 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004145 goto failed;
4146 }
4147
Johan Hedberga198e7b2012-02-17 14:27:06 +02004148 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004149 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004150 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4151 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4152 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004153 goto failed;
4154 }
4155
4156 if (cp->name_known) {
4157 e->name_state = NAME_KNOWN;
4158 list_del(&e->list);
4159 } else {
4160 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004161 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004162 }
4163
Johan Hedberge3846622013-01-09 15:29:33 +02004164 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4165 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004166
4167failed:
4168 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004169 return err;
4170}
4171
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004172static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004173 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004174{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004175 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004176 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004177 int err;
4178
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004179 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004180
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004181 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004182 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4183 MGMT_STATUS_INVALID_PARAMS,
4184 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004185
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004186 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004187
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004188 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4189 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004190 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004191 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004192 goto done;
4193 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004194
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004195 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4196 sk);
4197 status = MGMT_STATUS_SUCCESS;
4198
4199done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004200 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004201 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004202
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004203 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004204
4205 return err;
4206}
4207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004208static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004209 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004210{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004211 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004212 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004213 int err;
4214
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004215 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004216
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004217 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004218 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4219 MGMT_STATUS_INVALID_PARAMS,
4220 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004221
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004222 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004223
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004224 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4225 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004226 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004227 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004228 goto done;
4229 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004230
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004231 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4232 sk);
4233 status = MGMT_STATUS_SUCCESS;
4234
4235done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004236 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004237 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004238
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004239 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004240
4241 return err;
4242}
4243
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004244static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4245 u16 len)
4246{
4247 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004248 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004249 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004250 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004251
4252 BT_DBG("%s", hdev->name);
4253
Szymon Jancc72d4b82012-03-16 16:02:57 +01004254 source = __le16_to_cpu(cp->source);
4255
4256 if (source > 0x0002)
4257 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4258 MGMT_STATUS_INVALID_PARAMS);
4259
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004260 hci_dev_lock(hdev);
4261
Szymon Jancc72d4b82012-03-16 16:02:57 +01004262 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004263 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4264 hdev->devid_product = __le16_to_cpu(cp->product);
4265 hdev->devid_version = __le16_to_cpu(cp->version);
4266
4267 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4268
Johan Hedberg890ea892013-03-15 17:06:52 -05004269 hci_req_init(&req, hdev);
4270 update_eir(&req);
4271 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004272
4273 hci_dev_unlock(hdev);
4274
4275 return err;
4276}
4277
Johan Hedberg4375f102013-09-25 13:26:10 +03004278static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4279{
4280 struct cmd_lookup match = { NULL, hdev };
4281
4282 if (status) {
4283 u8 mgmt_err = mgmt_status(status);
4284
4285 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4286 cmd_status_rsp, &mgmt_err);
4287 return;
4288 }
4289
Johan Hedbergc93bd152014-07-08 15:07:48 +03004290 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4291 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4292 else
4293 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4294
Johan Hedberg4375f102013-09-25 13:26:10 +03004295 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4296 &match);
4297
4298 new_settings(hdev, match.sk);
4299
4300 if (match.sk)
4301 sock_put(match.sk);
4302}
4303
Marcel Holtmann21b51872013-10-10 09:47:53 -07004304static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4305 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004306{
4307 struct mgmt_mode *cp = data;
4308 struct pending_cmd *cmd;
4309 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004310 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004311 int err;
4312
4313 BT_DBG("request for %s", hdev->name);
4314
Johan Hedberge6fe7982013-10-02 15:45:22 +03004315 status = mgmt_le_support(hdev);
4316 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004317 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004318 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004319
4320 if (cp->val != 0x00 && cp->val != 0x01)
4321 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4322 MGMT_STATUS_INVALID_PARAMS);
4323
4324 hci_dev_lock(hdev);
4325
4326 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004327 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004328
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004329 /* The following conditions are ones which mean that we should
4330 * not do any HCI communication but directly send a mgmt
4331 * response to user space (after toggling the flag if
4332 * necessary).
4333 */
4334 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004335 hci_conn_num(hdev, LE_LINK) > 0 ||
4336 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4337 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004338 bool changed = false;
4339
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004340 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4341 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004342 changed = true;
4343 }
4344
4345 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4346 if (err < 0)
4347 goto unlock;
4348
4349 if (changed)
4350 err = new_settings(hdev, sk);
4351
4352 goto unlock;
4353 }
4354
4355 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4356 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4357 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4358 MGMT_STATUS_BUSY);
4359 goto unlock;
4360 }
4361
4362 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4363 if (!cmd) {
4364 err = -ENOMEM;
4365 goto unlock;
4366 }
4367
4368 hci_req_init(&req, hdev);
4369
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004370 if (val)
4371 enable_advertising(&req);
4372 else
4373 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004374
4375 err = hci_req_run(&req, set_advertising_complete);
4376 if (err < 0)
4377 mgmt_pending_remove(cmd);
4378
4379unlock:
4380 hci_dev_unlock(hdev);
4381 return err;
4382}
4383
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004384static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4385 void *data, u16 len)
4386{
4387 struct mgmt_cp_set_static_address *cp = data;
4388 int err;
4389
4390 BT_DBG("%s", hdev->name);
4391
Marcel Holtmann62af4442013-10-02 22:10:32 -07004392 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004393 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004394 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004395
4396 if (hdev_is_powered(hdev))
4397 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4398 MGMT_STATUS_REJECTED);
4399
4400 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4401 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4402 return cmd_status(sk, hdev->id,
4403 MGMT_OP_SET_STATIC_ADDRESS,
4404 MGMT_STATUS_INVALID_PARAMS);
4405
4406 /* Two most significant bits shall be set */
4407 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4408 return cmd_status(sk, hdev->id,
4409 MGMT_OP_SET_STATIC_ADDRESS,
4410 MGMT_STATUS_INVALID_PARAMS);
4411 }
4412
4413 hci_dev_lock(hdev);
4414
4415 bacpy(&hdev->static_addr, &cp->bdaddr);
4416
4417 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4418
4419 hci_dev_unlock(hdev);
4420
4421 return err;
4422}
4423
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004424static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4425 void *data, u16 len)
4426{
4427 struct mgmt_cp_set_scan_params *cp = data;
4428 __u16 interval, window;
4429 int err;
4430
4431 BT_DBG("%s", hdev->name);
4432
4433 if (!lmp_le_capable(hdev))
4434 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4435 MGMT_STATUS_NOT_SUPPORTED);
4436
4437 interval = __le16_to_cpu(cp->interval);
4438
4439 if (interval < 0x0004 || interval > 0x4000)
4440 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4441 MGMT_STATUS_INVALID_PARAMS);
4442
4443 window = __le16_to_cpu(cp->window);
4444
4445 if (window < 0x0004 || window > 0x4000)
4446 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4447 MGMT_STATUS_INVALID_PARAMS);
4448
Marcel Holtmann899e1072013-10-14 09:55:32 -07004449 if (window > interval)
4450 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4451 MGMT_STATUS_INVALID_PARAMS);
4452
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004453 hci_dev_lock(hdev);
4454
4455 hdev->le_scan_interval = interval;
4456 hdev->le_scan_window = window;
4457
4458 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4459
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004460 /* If background scan is running, restart it so new parameters are
4461 * loaded.
4462 */
4463 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4464 hdev->discovery.state == DISCOVERY_STOPPED) {
4465 struct hci_request req;
4466
4467 hci_req_init(&req, hdev);
4468
4469 hci_req_add_le_scan_disable(&req);
4470 hci_req_add_le_passive_scan(&req);
4471
4472 hci_req_run(&req, NULL);
4473 }
4474
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004475 hci_dev_unlock(hdev);
4476
4477 return err;
4478}
4479
Johan Hedberg33e38b32013-03-15 17:07:05 -05004480static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4481{
4482 struct pending_cmd *cmd;
4483
4484 BT_DBG("status 0x%02x", status);
4485
4486 hci_dev_lock(hdev);
4487
4488 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4489 if (!cmd)
4490 goto unlock;
4491
4492 if (status) {
4493 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4494 mgmt_status(status));
4495 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004496 struct mgmt_mode *cp = cmd->param;
4497
4498 if (cp->val)
4499 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4500 else
4501 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4502
Johan Hedberg33e38b32013-03-15 17:07:05 -05004503 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4504 new_settings(hdev, cmd->sk);
4505 }
4506
4507 mgmt_pending_remove(cmd);
4508
4509unlock:
4510 hci_dev_unlock(hdev);
4511}
4512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004513static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004514 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004515{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004516 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004517 struct pending_cmd *cmd;
4518 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004519 int err;
4520
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004521 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004522
Johan Hedberg56f87902013-10-02 13:43:13 +03004523 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4524 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004525 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4526 MGMT_STATUS_NOT_SUPPORTED);
4527
Johan Hedberga7e80f22013-01-09 16:05:19 +02004528 if (cp->val != 0x00 && cp->val != 0x01)
4529 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4530 MGMT_STATUS_INVALID_PARAMS);
4531
Johan Hedberg5400c042012-02-21 16:40:33 +02004532 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004533 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004534 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004535
4536 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004537 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004538 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004539
4540 hci_dev_lock(hdev);
4541
Johan Hedberg05cbf292013-03-15 17:07:07 -05004542 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4543 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4544 MGMT_STATUS_BUSY);
4545 goto unlock;
4546 }
4547
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004548 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4549 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4550 hdev);
4551 goto unlock;
4552 }
4553
Johan Hedberg33e38b32013-03-15 17:07:05 -05004554 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4555 data, len);
4556 if (!cmd) {
4557 err = -ENOMEM;
4558 goto unlock;
4559 }
4560
4561 hci_req_init(&req, hdev);
4562
Johan Hedberg406d7802013-03-15 17:07:09 -05004563 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004564
4565 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004566 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004567 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004568 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004569 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004570 }
4571
Johan Hedberg33e38b32013-03-15 17:07:05 -05004572unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004573 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004574
Antti Julkuf6422ec2011-06-22 13:11:56 +03004575 return err;
4576}
4577
Johan Hedberg0663ca22013-10-02 13:43:14 +03004578static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4579{
4580 struct pending_cmd *cmd;
4581
4582 BT_DBG("status 0x%02x", status);
4583
4584 hci_dev_lock(hdev);
4585
4586 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4587 if (!cmd)
4588 goto unlock;
4589
4590 if (status) {
4591 u8 mgmt_err = mgmt_status(status);
4592
4593 /* We need to restore the flag if related HCI commands
4594 * failed.
4595 */
4596 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4597
4598 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4599 } else {
4600 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4601 new_settings(hdev, cmd->sk);
4602 }
4603
4604 mgmt_pending_remove(cmd);
4605
4606unlock:
4607 hci_dev_unlock(hdev);
4608}
4609
4610static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4611{
4612 struct mgmt_mode *cp = data;
4613 struct pending_cmd *cmd;
4614 struct hci_request req;
4615 int err;
4616
4617 BT_DBG("request for %s", hdev->name);
4618
4619 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4620 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4621 MGMT_STATUS_NOT_SUPPORTED);
4622
4623 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4624 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4625 MGMT_STATUS_REJECTED);
4626
4627 if (cp->val != 0x00 && cp->val != 0x01)
4628 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4629 MGMT_STATUS_INVALID_PARAMS);
4630
4631 hci_dev_lock(hdev);
4632
4633 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4634 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4635 goto unlock;
4636 }
4637
4638 if (!hdev_is_powered(hdev)) {
4639 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004640 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4641 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4642 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4643 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4644 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4645 }
4646
4647 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4648
4649 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4650 if (err < 0)
4651 goto unlock;
4652
4653 err = new_settings(hdev, sk);
4654 goto unlock;
4655 }
4656
4657 /* Reject disabling when powered on */
4658 if (!cp->val) {
4659 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4660 MGMT_STATUS_REJECTED);
4661 goto unlock;
4662 }
4663
4664 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4665 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4666 MGMT_STATUS_BUSY);
4667 goto unlock;
4668 }
4669
4670 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4671 if (!cmd) {
4672 err = -ENOMEM;
4673 goto unlock;
4674 }
4675
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004676 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004677 * generates the correct flags.
4678 */
4679 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4680
4681 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004682
Johan Hedberg432df052014-08-01 11:13:31 +03004683 write_fast_connectable(&req, false);
4684 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004685
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004686 /* Since only the advertising data flags will change, there
4687 * is no need to update the scan response data.
4688 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004689 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004690
Johan Hedberg0663ca22013-10-02 13:43:14 +03004691 err = hci_req_run(&req, set_bredr_complete);
4692 if (err < 0)
4693 mgmt_pending_remove(cmd);
4694
4695unlock:
4696 hci_dev_unlock(hdev);
4697 return err;
4698}
4699
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004700static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4701 void *data, u16 len)
4702{
4703 struct mgmt_mode *cp = data;
4704 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004705 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004706 int err;
4707
4708 BT_DBG("request for %s", hdev->name);
4709
Johan Hedberga3209692014-05-26 11:23:35 +03004710 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4711 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004712 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4713 MGMT_STATUS_NOT_SUPPORTED);
4714
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004715 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004716 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4717 MGMT_STATUS_INVALID_PARAMS);
4718
4719 hci_dev_lock(hdev);
4720
Johan Hedberga3209692014-05-26 11:23:35 +03004721 if (!hdev_is_powered(hdev) ||
4722 (!lmp_sc_capable(hdev) &&
4723 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4724 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004725 bool changed;
4726
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004727 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004728 changed = !test_and_set_bit(HCI_SC_ENABLED,
4729 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004730 if (cp->val == 0x02)
4731 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4732 else
4733 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4734 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004735 changed = test_and_clear_bit(HCI_SC_ENABLED,
4736 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004737 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4738 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004739
4740 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4741 if (err < 0)
4742 goto failed;
4743
4744 if (changed)
4745 err = new_settings(hdev, sk);
4746
4747 goto failed;
4748 }
4749
4750 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4751 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4752 MGMT_STATUS_BUSY);
4753 goto failed;
4754 }
4755
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004756 val = !!cp->val;
4757
4758 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4759 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004760 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4761 goto failed;
4762 }
4763
4764 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4765 if (!cmd) {
4766 err = -ENOMEM;
4767 goto failed;
4768 }
4769
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004770 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004771 if (err < 0) {
4772 mgmt_pending_remove(cmd);
4773 goto failed;
4774 }
4775
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004776 if (cp->val == 0x02)
4777 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4778 else
4779 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4780
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004781failed:
4782 hci_dev_unlock(hdev);
4783 return err;
4784}
4785
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004786static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4787 void *data, u16 len)
4788{
4789 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004790 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004791 int err;
4792
4793 BT_DBG("request for %s", hdev->name);
4794
Johan Hedbergb97109792014-06-24 14:00:28 +03004795 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004796 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4797 MGMT_STATUS_INVALID_PARAMS);
4798
4799 hci_dev_lock(hdev);
4800
4801 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004802 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4803 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004804 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004805 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4806 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004807
Johan Hedbergb97109792014-06-24 14:00:28 +03004808 if (cp->val == 0x02)
4809 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4810 &hdev->dev_flags);
4811 else
4812 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4813 &hdev->dev_flags);
4814
4815 if (hdev_is_powered(hdev) && use_changed &&
4816 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4817 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4818 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4819 sizeof(mode), &mode);
4820 }
4821
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004822 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4823 if (err < 0)
4824 goto unlock;
4825
4826 if (changed)
4827 err = new_settings(hdev, sk);
4828
4829unlock:
4830 hci_dev_unlock(hdev);
4831 return err;
4832}
4833
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004834static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4835 u16 len)
4836{
4837 struct mgmt_cp_set_privacy *cp = cp_data;
4838 bool changed;
4839 int err;
4840
4841 BT_DBG("request for %s", hdev->name);
4842
4843 if (!lmp_le_capable(hdev))
4844 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4845 MGMT_STATUS_NOT_SUPPORTED);
4846
4847 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4848 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4849 MGMT_STATUS_INVALID_PARAMS);
4850
4851 if (hdev_is_powered(hdev))
4852 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4853 MGMT_STATUS_REJECTED);
4854
4855 hci_dev_lock(hdev);
4856
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004857 /* If user space supports this command it is also expected to
4858 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4859 */
4860 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4861
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004862 if (cp->privacy) {
4863 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4864 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4865 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4866 } else {
4867 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4868 memset(hdev->irk, 0, sizeof(hdev->irk));
4869 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4870 }
4871
4872 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4873 if (err < 0)
4874 goto unlock;
4875
4876 if (changed)
4877 err = new_settings(hdev, sk);
4878
4879unlock:
4880 hci_dev_unlock(hdev);
4881 return err;
4882}
4883
Johan Hedberg41edf162014-02-18 10:19:35 +02004884static bool irk_is_valid(struct mgmt_irk_info *irk)
4885{
4886 switch (irk->addr.type) {
4887 case BDADDR_LE_PUBLIC:
4888 return true;
4889
4890 case BDADDR_LE_RANDOM:
4891 /* Two most significant bits shall be set */
4892 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4893 return false;
4894 return true;
4895 }
4896
4897 return false;
4898}
4899
4900static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4901 u16 len)
4902{
4903 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004904 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4905 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004906 u16 irk_count, expected_len;
4907 int i, err;
4908
4909 BT_DBG("request for %s", hdev->name);
4910
4911 if (!lmp_le_capable(hdev))
4912 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4913 MGMT_STATUS_NOT_SUPPORTED);
4914
4915 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004916 if (irk_count > max_irk_count) {
4917 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4918 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4919 MGMT_STATUS_INVALID_PARAMS);
4920 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004921
4922 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4923 if (expected_len != len) {
4924 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004925 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004926 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4927 MGMT_STATUS_INVALID_PARAMS);
4928 }
4929
4930 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4931
4932 for (i = 0; i < irk_count; i++) {
4933 struct mgmt_irk_info *key = &cp->irks[i];
4934
4935 if (!irk_is_valid(key))
4936 return cmd_status(sk, hdev->id,
4937 MGMT_OP_LOAD_IRKS,
4938 MGMT_STATUS_INVALID_PARAMS);
4939 }
4940
4941 hci_dev_lock(hdev);
4942
4943 hci_smp_irks_clear(hdev);
4944
4945 for (i = 0; i < irk_count; i++) {
4946 struct mgmt_irk_info *irk = &cp->irks[i];
4947 u8 addr_type;
4948
4949 if (irk->addr.type == BDADDR_LE_PUBLIC)
4950 addr_type = ADDR_LE_DEV_PUBLIC;
4951 else
4952 addr_type = ADDR_LE_DEV_RANDOM;
4953
4954 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4955 BDADDR_ANY);
4956 }
4957
4958 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4959
4960 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4961
4962 hci_dev_unlock(hdev);
4963
4964 return err;
4965}
4966
Johan Hedberg3f706b72013-01-20 14:27:16 +02004967static bool ltk_is_valid(struct mgmt_ltk_info *key)
4968{
4969 if (key->master != 0x00 && key->master != 0x01)
4970 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004971
4972 switch (key->addr.type) {
4973 case BDADDR_LE_PUBLIC:
4974 return true;
4975
4976 case BDADDR_LE_RANDOM:
4977 /* Two most significant bits shall be set */
4978 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4979 return false;
4980 return true;
4981 }
4982
4983 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004984}
4985
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004986static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004987 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004988{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004989 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004990 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4991 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004992 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004993 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004994
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004995 BT_DBG("request for %s", hdev->name);
4996
4997 if (!lmp_le_capable(hdev))
4998 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4999 MGMT_STATUS_NOT_SUPPORTED);
5000
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005001 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005002 if (key_count > max_key_count) {
5003 BT_ERR("load_ltks: too big key_count value %u", key_count);
5004 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5005 MGMT_STATUS_INVALID_PARAMS);
5006 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005007
5008 expected_len = sizeof(*cp) + key_count *
5009 sizeof(struct mgmt_ltk_info);
5010 if (expected_len != len) {
5011 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005012 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005013 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005014 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005015 }
5016
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005017 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005018
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005019 for (i = 0; i < key_count; i++) {
5020 struct mgmt_ltk_info *key = &cp->keys[i];
5021
Johan Hedberg3f706b72013-01-20 14:27:16 +02005022 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005023 return cmd_status(sk, hdev->id,
5024 MGMT_OP_LOAD_LONG_TERM_KEYS,
5025 MGMT_STATUS_INVALID_PARAMS);
5026 }
5027
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005028 hci_dev_lock(hdev);
5029
5030 hci_smp_ltks_clear(hdev);
5031
5032 for (i = 0; i < key_count; i++) {
5033 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005034 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005035
5036 if (key->addr.type == BDADDR_LE_PUBLIC)
5037 addr_type = ADDR_LE_DEV_PUBLIC;
5038 else
5039 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005040
Johan Hedberg61b43352014-05-29 19:36:53 +03005041 switch (key->type) {
5042 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005043 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005044 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005045 break;
5046 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005047 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005048 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005049 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005050 case MGMT_LTK_P256_UNAUTH:
5051 authenticated = 0x00;
5052 type = SMP_LTK_P256;
5053 break;
5054 case MGMT_LTK_P256_AUTH:
5055 authenticated = 0x01;
5056 type = SMP_LTK_P256;
5057 break;
5058 case MGMT_LTK_P256_DEBUG:
5059 authenticated = 0x00;
5060 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005061 default:
5062 continue;
5063 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005064
Johan Hedberg35d70272014-02-19 14:57:47 +02005065 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005066 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005067 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005068 }
5069
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005070 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5071 NULL, 0);
5072
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005073 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005074
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005075 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005076}
5077
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005078static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005079{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005080 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005081 struct mgmt_rp_get_conn_info rp;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005082
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005083 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005084
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005085 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005086 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005087 rp.tx_power = conn->tx_power;
5088 rp.max_tx_power = conn->max_tx_power;
5089 } else {
5090 rp.rssi = HCI_RSSI_INVALID;
5091 rp.tx_power = HCI_TX_POWER_INVALID;
5092 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005093 }
5094
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005095 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5096 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005097
5098 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005099 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005100}
5101
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005102static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005103{
5104 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005105 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005106 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005107 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005108 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005109
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005110 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005111
5112 hci_dev_lock(hdev);
5113
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005114 /* Commands sent in request are either Read RSSI or Read Transmit Power
5115 * Level so we check which one was last sent to retrieve connection
5116 * handle. Both commands have handle as first parameter so it's safe to
5117 * cast data on the same command struct.
5118 *
5119 * First command sent is always Read RSSI and we fail only if it fails.
5120 * In other case we simply override error to indicate success as we
5121 * already remembered if TX power value is actually valid.
5122 */
5123 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5124 if (!cp) {
5125 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005126 status = MGMT_STATUS_SUCCESS;
5127 } else {
5128 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005129 }
5130
5131 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005132 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005133 goto unlock;
5134 }
5135
5136 handle = __le16_to_cpu(cp->handle);
5137 conn = hci_conn_hash_lookup_handle(hdev, handle);
5138 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005139 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005140 goto unlock;
5141 }
5142
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005143 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5144 if (!cmd)
5145 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005146
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005147 cmd->cmd_complete(cmd, status);
5148 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005149
5150unlock:
5151 hci_dev_unlock(hdev);
5152}
5153
5154static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5155 u16 len)
5156{
5157 struct mgmt_cp_get_conn_info *cp = data;
5158 struct mgmt_rp_get_conn_info rp;
5159 struct hci_conn *conn;
5160 unsigned long conn_info_age;
5161 int err = 0;
5162
5163 BT_DBG("%s", hdev->name);
5164
5165 memset(&rp, 0, sizeof(rp));
5166 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5167 rp.addr.type = cp->addr.type;
5168
5169 if (!bdaddr_type_is_valid(cp->addr.type))
5170 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5171 MGMT_STATUS_INVALID_PARAMS,
5172 &rp, sizeof(rp));
5173
5174 hci_dev_lock(hdev);
5175
5176 if (!hdev_is_powered(hdev)) {
5177 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5178 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5179 goto unlock;
5180 }
5181
5182 if (cp->addr.type == BDADDR_BREDR)
5183 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5184 &cp->addr.bdaddr);
5185 else
5186 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5187
5188 if (!conn || conn->state != BT_CONNECTED) {
5189 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5190 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5191 goto unlock;
5192 }
5193
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005194 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5195 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5196 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5197 goto unlock;
5198 }
5199
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005200 /* To avoid client trying to guess when to poll again for information we
5201 * calculate conn info age as random value between min/max set in hdev.
5202 */
5203 conn_info_age = hdev->conn_info_min_age +
5204 prandom_u32_max(hdev->conn_info_max_age -
5205 hdev->conn_info_min_age);
5206
5207 /* Query controller to refresh cached values if they are too old or were
5208 * never read.
5209 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005210 if (time_after(jiffies, conn->conn_info_timestamp +
5211 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005212 !conn->conn_info_timestamp) {
5213 struct hci_request req;
5214 struct hci_cp_read_tx_power req_txp_cp;
5215 struct hci_cp_read_rssi req_rssi_cp;
5216 struct pending_cmd *cmd;
5217
5218 hci_req_init(&req, hdev);
5219 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5220 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5221 &req_rssi_cp);
5222
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005223 /* For LE links TX power does not change thus we don't need to
5224 * query for it once value is known.
5225 */
5226 if (!bdaddr_type_is_le(cp->addr.type) ||
5227 conn->tx_power == HCI_TX_POWER_INVALID) {
5228 req_txp_cp.handle = cpu_to_le16(conn->handle);
5229 req_txp_cp.type = 0x00;
5230 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5231 sizeof(req_txp_cp), &req_txp_cp);
5232 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005233
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005234 /* Max TX power needs to be read only once per connection */
5235 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5236 req_txp_cp.handle = cpu_to_le16(conn->handle);
5237 req_txp_cp.type = 0x01;
5238 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5239 sizeof(req_txp_cp), &req_txp_cp);
5240 }
5241
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005242 err = hci_req_run(&req, conn_info_refresh_complete);
5243 if (err < 0)
5244 goto unlock;
5245
5246 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5247 data, len);
5248 if (!cmd) {
5249 err = -ENOMEM;
5250 goto unlock;
5251 }
5252
5253 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005254 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005255 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005256
5257 conn->conn_info_timestamp = jiffies;
5258 } else {
5259 /* Cache is valid, just reply with values cached in hci_conn */
5260 rp.rssi = conn->rssi;
5261 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005262 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005263
5264 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5265 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5266 }
5267
5268unlock:
5269 hci_dev_unlock(hdev);
5270 return err;
5271}
5272
Johan Hedberg69487372014-12-05 13:36:07 +02005273static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
5274{
5275 struct hci_conn *conn = cmd->user_data;
5276 struct mgmt_rp_get_clock_info rp;
5277 struct hci_dev *hdev;
5278
5279 memset(&rp, 0, sizeof(rp));
5280 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5281
5282 if (status)
5283 goto complete;
5284
5285 hdev = hci_dev_get(cmd->index);
5286 if (hdev) {
5287 rp.local_clock = cpu_to_le32(hdev->clock);
5288 hci_dev_put(hdev);
5289 }
5290
5291 if (conn) {
5292 rp.piconet_clock = cpu_to_le32(conn->clock);
5293 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5294 }
5295
5296complete:
5297 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
5298
5299 if (conn) {
5300 hci_conn_drop(conn);
5301 hci_conn_put(conn);
5302 }
5303}
5304
Johan Hedberg95868422014-06-28 17:54:07 +03005305static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5306{
Johan Hedberg95868422014-06-28 17:54:07 +03005307 struct hci_cp_read_clock *hci_cp;
5308 struct pending_cmd *cmd;
5309 struct hci_conn *conn;
5310
5311 BT_DBG("%s status %u", hdev->name, status);
5312
5313 hci_dev_lock(hdev);
5314
5315 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5316 if (!hci_cp)
5317 goto unlock;
5318
5319 if (hci_cp->which) {
5320 u16 handle = __le16_to_cpu(hci_cp->handle);
5321 conn = hci_conn_hash_lookup_handle(hdev, handle);
5322 } else {
5323 conn = NULL;
5324 }
5325
5326 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5327 if (!cmd)
5328 goto unlock;
5329
Johan Hedberg69487372014-12-05 13:36:07 +02005330 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005331 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005332
5333unlock:
5334 hci_dev_unlock(hdev);
5335}
5336
5337static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5338 u16 len)
5339{
5340 struct mgmt_cp_get_clock_info *cp = data;
5341 struct mgmt_rp_get_clock_info rp;
5342 struct hci_cp_read_clock hci_cp;
5343 struct pending_cmd *cmd;
5344 struct hci_request req;
5345 struct hci_conn *conn;
5346 int err;
5347
5348 BT_DBG("%s", hdev->name);
5349
5350 memset(&rp, 0, sizeof(rp));
5351 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5352 rp.addr.type = cp->addr.type;
5353
5354 if (cp->addr.type != BDADDR_BREDR)
5355 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5356 MGMT_STATUS_INVALID_PARAMS,
5357 &rp, sizeof(rp));
5358
5359 hci_dev_lock(hdev);
5360
5361 if (!hdev_is_powered(hdev)) {
5362 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5363 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5364 goto unlock;
5365 }
5366
5367 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5368 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5369 &cp->addr.bdaddr);
5370 if (!conn || conn->state != BT_CONNECTED) {
5371 err = cmd_complete(sk, hdev->id,
5372 MGMT_OP_GET_CLOCK_INFO,
5373 MGMT_STATUS_NOT_CONNECTED,
5374 &rp, sizeof(rp));
5375 goto unlock;
5376 }
5377 } else {
5378 conn = NULL;
5379 }
5380
5381 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5382 if (!cmd) {
5383 err = -ENOMEM;
5384 goto unlock;
5385 }
5386
Johan Hedberg69487372014-12-05 13:36:07 +02005387 cmd->cmd_complete = clock_info_cmd_complete;
5388
Johan Hedberg95868422014-06-28 17:54:07 +03005389 hci_req_init(&req, hdev);
5390
5391 memset(&hci_cp, 0, sizeof(hci_cp));
5392 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5393
5394 if (conn) {
5395 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005396 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005397
5398 hci_cp.handle = cpu_to_le16(conn->handle);
5399 hci_cp.which = 0x01; /* Piconet clock */
5400 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5401 }
5402
5403 err = hci_req_run(&req, get_clock_info_complete);
5404 if (err < 0)
5405 mgmt_pending_remove(cmd);
5406
5407unlock:
5408 hci_dev_unlock(hdev);
5409 return err;
5410}
5411
Marcel Holtmann8afef092014-06-29 22:28:34 +02005412static void device_added(struct sock *sk, struct hci_dev *hdev,
5413 bdaddr_t *bdaddr, u8 type, u8 action)
5414{
5415 struct mgmt_ev_device_added ev;
5416
5417 bacpy(&ev.addr.bdaddr, bdaddr);
5418 ev.addr.type = type;
5419 ev.action = action;
5420
5421 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5422}
5423
Marcel Holtmann2faade52014-06-29 19:44:03 +02005424static int add_device(struct sock *sk, struct hci_dev *hdev,
5425 void *data, u16 len)
5426{
5427 struct mgmt_cp_add_device *cp = data;
5428 u8 auto_conn, addr_type;
5429 int err;
5430
5431 BT_DBG("%s", hdev->name);
5432
Johan Hedberg66593582014-07-09 12:59:14 +03005433 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005434 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5435 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5436 MGMT_STATUS_INVALID_PARAMS,
5437 &cp->addr, sizeof(cp->addr));
5438
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005439 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005440 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5441 MGMT_STATUS_INVALID_PARAMS,
5442 &cp->addr, sizeof(cp->addr));
5443
5444 hci_dev_lock(hdev);
5445
Johan Hedberg66593582014-07-09 12:59:14 +03005446 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005447 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005448 if (cp->action != 0x01) {
5449 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5450 MGMT_STATUS_INVALID_PARAMS,
5451 &cp->addr, sizeof(cp->addr));
5452 goto unlock;
5453 }
5454
5455 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5456 cp->addr.type);
5457 if (err)
5458 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005459
Johan Hedberg432df052014-08-01 11:13:31 +03005460 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005461
Johan Hedberg66593582014-07-09 12:59:14 +03005462 goto added;
5463 }
5464
Marcel Holtmann2faade52014-06-29 19:44:03 +02005465 if (cp->addr.type == BDADDR_LE_PUBLIC)
5466 addr_type = ADDR_LE_DEV_PUBLIC;
5467 else
5468 addr_type = ADDR_LE_DEV_RANDOM;
5469
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005470 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005471 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005472 else if (cp->action == 0x01)
5473 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005474 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005475 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005476
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005477 /* If the connection parameters don't exist for this device,
5478 * they will be created and configured with defaults.
5479 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005480 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5481 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005482 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5483 MGMT_STATUS_FAILED,
5484 &cp->addr, sizeof(cp->addr));
5485 goto unlock;
5486 }
5487
Johan Hedberg66593582014-07-09 12:59:14 +03005488added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005489 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5490
Marcel Holtmann2faade52014-06-29 19:44:03 +02005491 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5492 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5493
5494unlock:
5495 hci_dev_unlock(hdev);
5496 return err;
5497}
5498
Marcel Holtmann8afef092014-06-29 22:28:34 +02005499static void device_removed(struct sock *sk, struct hci_dev *hdev,
5500 bdaddr_t *bdaddr, u8 type)
5501{
5502 struct mgmt_ev_device_removed ev;
5503
5504 bacpy(&ev.addr.bdaddr, bdaddr);
5505 ev.addr.type = type;
5506
5507 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5508}
5509
Marcel Holtmann2faade52014-06-29 19:44:03 +02005510static int remove_device(struct sock *sk, struct hci_dev *hdev,
5511 void *data, u16 len)
5512{
5513 struct mgmt_cp_remove_device *cp = data;
5514 int err;
5515
5516 BT_DBG("%s", hdev->name);
5517
5518 hci_dev_lock(hdev);
5519
5520 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005521 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005522 u8 addr_type;
5523
Johan Hedberg66593582014-07-09 12:59:14 +03005524 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005525 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5526 MGMT_STATUS_INVALID_PARAMS,
5527 &cp->addr, sizeof(cp->addr));
5528 goto unlock;
5529 }
5530
Johan Hedberg66593582014-07-09 12:59:14 +03005531 if (cp->addr.type == BDADDR_BREDR) {
5532 err = hci_bdaddr_list_del(&hdev->whitelist,
5533 &cp->addr.bdaddr,
5534 cp->addr.type);
5535 if (err) {
5536 err = cmd_complete(sk, hdev->id,
5537 MGMT_OP_REMOVE_DEVICE,
5538 MGMT_STATUS_INVALID_PARAMS,
5539 &cp->addr, sizeof(cp->addr));
5540 goto unlock;
5541 }
5542
Johan Hedberg432df052014-08-01 11:13:31 +03005543 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005544
Johan Hedberg66593582014-07-09 12:59:14 +03005545 device_removed(sk, hdev, &cp->addr.bdaddr,
5546 cp->addr.type);
5547 goto complete;
5548 }
5549
Marcel Holtmann2faade52014-06-29 19:44:03 +02005550 if (cp->addr.type == BDADDR_LE_PUBLIC)
5551 addr_type = ADDR_LE_DEV_PUBLIC;
5552 else
5553 addr_type = ADDR_LE_DEV_RANDOM;
5554
Johan Hedbergc71593d2014-07-02 17:37:28 +03005555 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5556 addr_type);
5557 if (!params) {
5558 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5559 MGMT_STATUS_INVALID_PARAMS,
5560 &cp->addr, sizeof(cp->addr));
5561 goto unlock;
5562 }
5563
5564 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5565 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5566 MGMT_STATUS_INVALID_PARAMS,
5567 &cp->addr, sizeof(cp->addr));
5568 goto unlock;
5569 }
5570
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005571 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005572 list_del(&params->list);
5573 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005574 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005575
5576 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005577 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005578 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005579 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005580
Marcel Holtmann2faade52014-06-29 19:44:03 +02005581 if (cp->addr.type) {
5582 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5583 MGMT_STATUS_INVALID_PARAMS,
5584 &cp->addr, sizeof(cp->addr));
5585 goto unlock;
5586 }
5587
Johan Hedberg66593582014-07-09 12:59:14 +03005588 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5589 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5590 list_del(&b->list);
5591 kfree(b);
5592 }
5593
Johan Hedberg432df052014-08-01 11:13:31 +03005594 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005595
Johan Hedberg19de0822014-07-06 13:06:51 +03005596 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5597 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5598 continue;
5599 device_removed(sk, hdev, &p->addr, p->addr_type);
5600 list_del(&p->action);
5601 list_del(&p->list);
5602 kfree(p);
5603 }
5604
5605 BT_DBG("All LE connection parameters were removed");
5606
5607 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005608 }
5609
Johan Hedberg66593582014-07-09 12:59:14 +03005610complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005611 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5612 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5613
5614unlock:
5615 hci_dev_unlock(hdev);
5616 return err;
5617}
5618
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005619static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5620 u16 len)
5621{
5622 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005623 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5624 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005625 u16 param_count, expected_len;
5626 int i;
5627
5628 if (!lmp_le_capable(hdev))
5629 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5630 MGMT_STATUS_NOT_SUPPORTED);
5631
5632 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005633 if (param_count > max_param_count) {
5634 BT_ERR("load_conn_param: too big param_count value %u",
5635 param_count);
5636 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5637 MGMT_STATUS_INVALID_PARAMS);
5638 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005639
5640 expected_len = sizeof(*cp) + param_count *
5641 sizeof(struct mgmt_conn_param);
5642 if (expected_len != len) {
5643 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5644 expected_len, len);
5645 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5646 MGMT_STATUS_INVALID_PARAMS);
5647 }
5648
5649 BT_DBG("%s param_count %u", hdev->name, param_count);
5650
5651 hci_dev_lock(hdev);
5652
5653 hci_conn_params_clear_disabled(hdev);
5654
5655 for (i = 0; i < param_count; i++) {
5656 struct mgmt_conn_param *param = &cp->params[i];
5657 struct hci_conn_params *hci_param;
5658 u16 min, max, latency, timeout;
5659 u8 addr_type;
5660
5661 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5662 param->addr.type);
5663
5664 if (param->addr.type == BDADDR_LE_PUBLIC) {
5665 addr_type = ADDR_LE_DEV_PUBLIC;
5666 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5667 addr_type = ADDR_LE_DEV_RANDOM;
5668 } else {
5669 BT_ERR("Ignoring invalid connection parameters");
5670 continue;
5671 }
5672
5673 min = le16_to_cpu(param->min_interval);
5674 max = le16_to_cpu(param->max_interval);
5675 latency = le16_to_cpu(param->latency);
5676 timeout = le16_to_cpu(param->timeout);
5677
5678 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5679 min, max, latency, timeout);
5680
5681 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5682 BT_ERR("Ignoring invalid connection parameters");
5683 continue;
5684 }
5685
5686 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5687 addr_type);
5688 if (!hci_param) {
5689 BT_ERR("Failed to add connection parameters");
5690 continue;
5691 }
5692
5693 hci_param->conn_min_interval = min;
5694 hci_param->conn_max_interval = max;
5695 hci_param->conn_latency = latency;
5696 hci_param->supervision_timeout = timeout;
5697 }
5698
5699 hci_dev_unlock(hdev);
5700
5701 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5702}
5703
Marcel Holtmanndbece372014-07-04 18:11:55 +02005704static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5705 void *data, u16 len)
5706{
5707 struct mgmt_cp_set_external_config *cp = data;
5708 bool changed;
5709 int err;
5710
5711 BT_DBG("%s", hdev->name);
5712
5713 if (hdev_is_powered(hdev))
5714 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5715 MGMT_STATUS_REJECTED);
5716
5717 if (cp->config != 0x00 && cp->config != 0x01)
5718 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5719 MGMT_STATUS_INVALID_PARAMS);
5720
5721 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5722 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5723 MGMT_STATUS_NOT_SUPPORTED);
5724
5725 hci_dev_lock(hdev);
5726
5727 if (cp->config)
5728 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5729 &hdev->dev_flags);
5730 else
5731 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5732 &hdev->dev_flags);
5733
5734 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5735 if (err < 0)
5736 goto unlock;
5737
5738 if (!changed)
5739 goto unlock;
5740
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005741 err = new_options(hdev, sk);
5742
Marcel Holtmanndbece372014-07-04 18:11:55 +02005743 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5744 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005745
5746 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5747 set_bit(HCI_CONFIG, &hdev->dev_flags);
5748 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5749
5750 queue_work(hdev->req_workqueue, &hdev->power_on);
5751 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005752 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005753 mgmt_index_added(hdev);
5754 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005755 }
5756
5757unlock:
5758 hci_dev_unlock(hdev);
5759 return err;
5760}
5761
Marcel Holtmann9713c172014-07-06 12:11:15 +02005762static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5763 void *data, u16 len)
5764{
5765 struct mgmt_cp_set_public_address *cp = data;
5766 bool changed;
5767 int err;
5768
5769 BT_DBG("%s", hdev->name);
5770
5771 if (hdev_is_powered(hdev))
5772 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5773 MGMT_STATUS_REJECTED);
5774
5775 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5776 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5777 MGMT_STATUS_INVALID_PARAMS);
5778
5779 if (!hdev->set_bdaddr)
5780 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5781 MGMT_STATUS_NOT_SUPPORTED);
5782
5783 hci_dev_lock(hdev);
5784
5785 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5786 bacpy(&hdev->public_addr, &cp->bdaddr);
5787
5788 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5789 if (err < 0)
5790 goto unlock;
5791
5792 if (!changed)
5793 goto unlock;
5794
5795 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5796 err = new_options(hdev, sk);
5797
5798 if (is_configured(hdev)) {
5799 mgmt_index_removed(hdev);
5800
5801 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5802
5803 set_bit(HCI_CONFIG, &hdev->dev_flags);
5804 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5805
5806 queue_work(hdev->req_workqueue, &hdev->power_on);
5807 }
5808
5809unlock:
5810 hci_dev_unlock(hdev);
5811 return err;
5812}
5813
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005814static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005815 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5816 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005817 bool var_len;
5818 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005819} mgmt_handlers[] = {
5820 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005821 { read_version, false, MGMT_READ_VERSION_SIZE },
5822 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5823 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5824 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5825 { set_powered, false, MGMT_SETTING_SIZE },
5826 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5827 { set_connectable, false, MGMT_SETTING_SIZE },
5828 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005829 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005830 { set_link_security, false, MGMT_SETTING_SIZE },
5831 { set_ssp, false, MGMT_SETTING_SIZE },
5832 { set_hs, false, MGMT_SETTING_SIZE },
5833 { set_le, false, MGMT_SETTING_SIZE },
5834 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5835 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5836 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5837 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5838 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5839 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5840 { disconnect, false, MGMT_DISCONNECT_SIZE },
5841 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5842 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5843 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5844 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5845 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5846 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5847 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5848 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5849 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5850 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5851 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5852 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005853 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005854 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5855 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5856 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5857 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5858 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5859 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005860 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005861 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005862 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005863 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005864 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005865 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005866 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005867 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005868 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005869 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005870 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005871 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5872 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005873 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5874 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005875 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005876 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005877 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005878 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005879};
5880
Johan Hedberg03811012010-12-08 00:21:06 +02005881int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5882{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005883 void *buf;
5884 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005885 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005886 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005887 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005888 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005889 int err;
5890
5891 BT_DBG("got %zu bytes", msglen);
5892
5893 if (msglen < sizeof(*hdr))
5894 return -EINVAL;
5895
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005896 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005897 if (!buf)
5898 return -ENOMEM;
5899
5900 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5901 err = -EFAULT;
5902 goto done;
5903 }
5904
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005905 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005906 opcode = __le16_to_cpu(hdr->opcode);
5907 index = __le16_to_cpu(hdr->index);
5908 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005909
5910 if (len != msglen - sizeof(*hdr)) {
5911 err = -EINVAL;
5912 goto done;
5913 }
5914
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005915 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005916 hdev = hci_dev_get(index);
5917 if (!hdev) {
5918 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005919 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005920 goto done;
5921 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005922
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005923 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005924 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005925 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005926 err = cmd_status(sk, index, opcode,
5927 MGMT_STATUS_INVALID_INDEX);
5928 goto done;
5929 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005930
5931 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005932 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005933 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5934 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005935 err = cmd_status(sk, index, opcode,
5936 MGMT_STATUS_INVALID_INDEX);
5937 goto done;
5938 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005939 }
5940
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005941 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005942 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005943 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005944 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005945 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005946 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005947 }
5948
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005949 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5950 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5951 err = cmd_status(sk, index, opcode,
5952 MGMT_STATUS_INVALID_INDEX);
5953 goto done;
5954 }
5955
5956 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5957 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005958 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005959 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005960 goto done;
5961 }
5962
Johan Hedbergbe22b542012-03-01 22:24:41 +02005963 handler = &mgmt_handlers[opcode];
5964
5965 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005966 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005967 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005968 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005969 goto done;
5970 }
5971
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005972 if (hdev)
5973 mgmt_init_hdev(sk, hdev);
5974
5975 cp = buf + sizeof(*hdr);
5976
Johan Hedbergbe22b542012-03-01 22:24:41 +02005977 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005978 if (err < 0)
5979 goto done;
5980
Johan Hedberg03811012010-12-08 00:21:06 +02005981 err = msglen;
5982
5983done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005984 if (hdev)
5985 hci_dev_put(hdev);
5986
Johan Hedberg03811012010-12-08 00:21:06 +02005987 kfree(buf);
5988 return err;
5989}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005990
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005991void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005992{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005993 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005994 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005995
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005996 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5997 return;
5998
5999 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6000 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6001 else
6002 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006003}
6004
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006005void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006006{
Johan Hedberg5f159032012-03-02 03:13:19 +02006007 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006008
Marcel Holtmann1514b892013-10-06 08:25:01 -07006009 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006010 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006011
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006012 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6013 return;
6014
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006015 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006016
Marcel Holtmannedd38962014-07-02 21:30:55 +02006017 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6018 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6019 else
6020 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006021}
6022
Andre Guedes6046dc32014-02-26 20:21:51 -03006023/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006024static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006025{
6026 struct hci_conn_params *p;
6027
6028 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006029 /* Needed for AUTO_OFF case where might not "really"
6030 * have been powered off.
6031 */
6032 list_del_init(&p->action);
6033
6034 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006035 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006036 case HCI_AUTO_CONN_ALWAYS:
6037 list_add(&p->action, &hdev->pend_le_conns);
6038 break;
6039 case HCI_AUTO_CONN_REPORT:
6040 list_add(&p->action, &hdev->pend_le_reports);
6041 break;
6042 default:
6043 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006044 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006045 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006046
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006047 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006048}
6049
Johan Hedberg229ab392013-03-15 17:06:53 -05006050static void powered_complete(struct hci_dev *hdev, u8 status)
6051{
6052 struct cmd_lookup match = { NULL, hdev };
6053
6054 BT_DBG("status 0x%02x", status);
6055
6056 hci_dev_lock(hdev);
6057
Johan Hedbergd7347f32014-07-04 12:37:23 +03006058 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006059
Johan Hedberg229ab392013-03-15 17:06:53 -05006060 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6061
6062 new_settings(hdev, match.sk);
6063
6064 hci_dev_unlock(hdev);
6065
6066 if (match.sk)
6067 sock_put(match.sk);
6068}
6069
Johan Hedberg70da6242013-03-15 17:06:51 -05006070static int powered_update_hci(struct hci_dev *hdev)
6071{
Johan Hedberg890ea892013-03-15 17:06:52 -05006072 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006073 u8 link_sec;
6074
Johan Hedberg890ea892013-03-15 17:06:52 -05006075 hci_req_init(&req, hdev);
6076
Johan Hedberg70da6242013-03-15 17:06:51 -05006077 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6078 !lmp_host_ssp_capable(hdev)) {
6079 u8 ssp = 1;
6080
Johan Hedberg890ea892013-03-15 17:06:52 -05006081 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006082 }
6083
Johan Hedbergc73eee92013-04-19 18:35:21 +03006084 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6085 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006086 struct hci_cp_write_le_host_supported cp;
6087
Marcel Holtmann32226e42014-07-24 20:04:16 +02006088 cp.le = 0x01;
6089 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006090
6091 /* Check first if we already have the right
6092 * host state (host features set)
6093 */
6094 if (cp.le != lmp_host_le_capable(hdev) ||
6095 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006096 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6097 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006098 }
6099
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006100 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006101 /* Make sure the controller has a good default for
6102 * advertising data. This also applies to the case
6103 * where BR/EDR was toggled during the AUTO_OFF phase.
6104 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006105 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006106 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006107 update_scan_rsp_data(&req);
6108 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006109
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006110 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6111 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006112 }
6113
Johan Hedberg70da6242013-03-15 17:06:51 -05006114 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6115 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006116 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6117 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006118
6119 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006120 write_fast_connectable(&req, false);
6121 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006122 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006123 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006124 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006125 }
6126
Johan Hedberg229ab392013-03-15 17:06:53 -05006127 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006128}
6129
Johan Hedberg744cf192011-11-08 20:40:14 +02006130int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006131{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006132 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006133 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6134 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006135 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006136
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006137 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6138 return 0;
6139
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006140 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006141 if (powered_update_hci(hdev) == 0)
6142 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006143
Johan Hedberg229ab392013-03-15 17:06:53 -05006144 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6145 &match);
6146 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006147 }
6148
Johan Hedberg229ab392013-03-15 17:06:53 -05006149 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006150 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006151
6152 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6153 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6154 zero_cod, sizeof(zero_cod), NULL);
6155
6156new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006157 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006158
6159 if (match.sk)
6160 sock_put(match.sk);
6161
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006162 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006163}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006164
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006165void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006166{
6167 struct pending_cmd *cmd;
6168 u8 status;
6169
6170 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6171 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006172 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006173
6174 if (err == -ERFKILL)
6175 status = MGMT_STATUS_RFKILLED;
6176 else
6177 status = MGMT_STATUS_FAILED;
6178
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006179 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006180
6181 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006182}
6183
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006184void mgmt_discoverable_timeout(struct hci_dev *hdev)
6185{
6186 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006187
6188 hci_dev_lock(hdev);
6189
6190 /* When discoverable timeout triggers, then just make sure
6191 * the limited discoverable flag is cleared. Even in the case
6192 * of a timeout triggered from general discoverable, it is
6193 * safe to unconditionally clear the flag.
6194 */
6195 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006196 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006197
6198 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006199 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6200 u8 scan = SCAN_PAGE;
6201 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6202 sizeof(scan), &scan);
6203 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006204 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006205 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006206 hci_req_run(&req, NULL);
6207
6208 hdev->discov_timeout = 0;
6209
Johan Hedberg9a43e252013-10-20 19:00:07 +03006210 new_settings(hdev, NULL);
6211
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006212 hci_dev_unlock(hdev);
6213}
6214
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006215void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6216 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006217{
Johan Hedberg86742e12011-11-07 23:13:38 +02006218 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006219
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006220 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006221
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006222 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006223 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006224 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006225 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006226 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006227 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006228
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006229 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006230}
Johan Hedbergf7520542011-01-20 12:34:39 +02006231
Johan Hedbergd7b25452014-05-23 13:19:53 +03006232static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6233{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006234 switch (ltk->type) {
6235 case SMP_LTK:
6236 case SMP_LTK_SLAVE:
6237 if (ltk->authenticated)
6238 return MGMT_LTK_AUTHENTICATED;
6239 return MGMT_LTK_UNAUTHENTICATED;
6240 case SMP_LTK_P256:
6241 if (ltk->authenticated)
6242 return MGMT_LTK_P256_AUTH;
6243 return MGMT_LTK_P256_UNAUTH;
6244 case SMP_LTK_P256_DEBUG:
6245 return MGMT_LTK_P256_DEBUG;
6246 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006247
6248 return MGMT_LTK_UNAUTHENTICATED;
6249}
6250
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006251void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006252{
6253 struct mgmt_ev_new_long_term_key ev;
6254
6255 memset(&ev, 0, sizeof(ev));
6256
Marcel Holtmann5192d302014-02-19 17:11:58 -08006257 /* Devices using resolvable or non-resolvable random addresses
6258 * without providing an indentity resolving key don't require
6259 * to store long term keys. Their addresses will change the
6260 * next time around.
6261 *
6262 * Only when a remote device provides an identity address
6263 * make sure the long term key is stored. If the remote
6264 * identity is known, the long term keys are internally
6265 * mapped to the identity address. So allow static random
6266 * and public addresses here.
6267 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006268 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6269 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6270 ev.store_hint = 0x00;
6271 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006272 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006273
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006274 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006275 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006276 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006277 ev.key.enc_size = key->enc_size;
6278 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006279 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006280
Johan Hedberg2ceba532014-06-16 19:25:16 +03006281 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006282 ev.key.master = 1;
6283
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006284 memcpy(ev.key.val, key->val, sizeof(key->val));
6285
Marcel Holtmann083368f2013-10-15 14:26:29 -07006286 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006287}
6288
Johan Hedberg95fbac82014-02-19 15:18:31 +02006289void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6290{
6291 struct mgmt_ev_new_irk ev;
6292
6293 memset(&ev, 0, sizeof(ev));
6294
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006295 /* For identity resolving keys from devices that are already
6296 * using a public address or static random address, do not
6297 * ask for storing this key. The identity resolving key really
6298 * is only mandatory for devices using resovlable random
6299 * addresses.
6300 *
6301 * Storing all identity resolving keys has the downside that
6302 * they will be also loaded on next boot of they system. More
6303 * identity resolving keys, means more time during scanning is
6304 * needed to actually resolve these addresses.
6305 */
6306 if (bacmp(&irk->rpa, BDADDR_ANY))
6307 ev.store_hint = 0x01;
6308 else
6309 ev.store_hint = 0x00;
6310
Johan Hedberg95fbac82014-02-19 15:18:31 +02006311 bacpy(&ev.rpa, &irk->rpa);
6312 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6313 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6314 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6315
6316 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6317}
6318
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006319void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6320 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006321{
6322 struct mgmt_ev_new_csrk ev;
6323
6324 memset(&ev, 0, sizeof(ev));
6325
6326 /* Devices using resolvable or non-resolvable random addresses
6327 * without providing an indentity resolving key don't require
6328 * to store signature resolving keys. Their addresses will change
6329 * the next time around.
6330 *
6331 * Only when a remote device provides an identity address
6332 * make sure the signature resolving key is stored. So allow
6333 * static random and public addresses here.
6334 */
6335 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6336 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6337 ev.store_hint = 0x00;
6338 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006339 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006340
6341 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6342 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6343 ev.key.master = csrk->master;
6344 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6345
6346 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6347}
6348
Andre Guedesffb5a8272014-07-01 18:10:11 -03006349void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006350 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6351 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006352{
6353 struct mgmt_ev_new_conn_param ev;
6354
Johan Hedbergc103aea2014-07-02 17:37:34 +03006355 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6356 return;
6357
Andre Guedesffb5a8272014-07-01 18:10:11 -03006358 memset(&ev, 0, sizeof(ev));
6359 bacpy(&ev.addr.bdaddr, bdaddr);
6360 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006361 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006362 ev.min_interval = cpu_to_le16(min_interval);
6363 ev.max_interval = cpu_to_le16(max_interval);
6364 ev.latency = cpu_to_le16(latency);
6365 ev.timeout = cpu_to_le16(timeout);
6366
6367 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6368}
6369
Marcel Holtmann94933992013-10-15 10:26:39 -07006370static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6371 u8 data_len)
6372{
6373 eir[eir_len++] = sizeof(type) + data_len;
6374 eir[eir_len++] = type;
6375 memcpy(&eir[eir_len], data, data_len);
6376 eir_len += data_len;
6377
6378 return eir_len;
6379}
6380
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006381void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6382 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006383{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006384 char buf[512];
6385 struct mgmt_ev_device_connected *ev = (void *) buf;
6386 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006387
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006388 bacpy(&ev->addr.bdaddr, &conn->dst);
6389 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006390
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006391 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006392
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006393 /* We must ensure that the EIR Data fields are ordered and
6394 * unique. Keep it simple for now and avoid the problem by not
6395 * adding any BR/EDR data to the LE adv.
6396 */
6397 if (conn->le_adv_data_len > 0) {
6398 memcpy(&ev->eir[eir_len],
6399 conn->le_adv_data, conn->le_adv_data_len);
6400 eir_len = conn->le_adv_data_len;
6401 } else {
6402 if (name_len > 0)
6403 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6404 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006405
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006406 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006407 eir_len = eir_append_data(ev->eir, eir_len,
6408 EIR_CLASS_OF_DEV,
6409 conn->dev_class, 3);
6410 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006411
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006412 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006413
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006414 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6415 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006416}
6417
Johan Hedberg8962ee72011-01-20 12:40:27 +02006418static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6419{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006420 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006421
Johan Hedbergf5818c22014-12-05 13:36:02 +02006422 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006423
6424 *sk = cmd->sk;
6425 sock_hold(*sk);
6426
Johan Hedberga664b5b2011-02-19 12:06:02 -03006427 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006428}
6429
Johan Hedberg124f6e32012-02-09 13:50:12 +02006430static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006431{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006432 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006433 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006434
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006435 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6436
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006437 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006438 mgmt_pending_remove(cmd);
6439}
6440
Johan Hedberg84c61d92014-08-01 11:13:30 +03006441bool mgmt_powering_down(struct hci_dev *hdev)
6442{
6443 struct pending_cmd *cmd;
6444 struct mgmt_mode *cp;
6445
6446 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6447 if (!cmd)
6448 return false;
6449
6450 cp = cmd->param;
6451 if (!cp->val)
6452 return true;
6453
6454 return false;
6455}
6456
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006457void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006458 u8 link_type, u8 addr_type, u8 reason,
6459 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006460{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006461 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006462 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006463
Johan Hedberg84c61d92014-08-01 11:13:30 +03006464 /* The connection is still in hci_conn_hash so test for 1
6465 * instead of 0 to know if this is the last one.
6466 */
6467 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6468 cancel_delayed_work(&hdev->power_off);
6469 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006470 }
6471
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006472 if (!mgmt_connected)
6473 return;
6474
Andre Guedes57eb7762013-10-30 19:01:41 -03006475 if (link_type != ACL_LINK && link_type != LE_LINK)
6476 return;
6477
Johan Hedberg744cf192011-11-08 20:40:14 +02006478 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006479
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006480 bacpy(&ev.addr.bdaddr, bdaddr);
6481 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6482 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006483
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006484 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006485
6486 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006487 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006488
Johan Hedberg124f6e32012-02-09 13:50:12 +02006489 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006490 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006491}
6492
Marcel Holtmann78929242013-10-06 23:55:47 -07006493void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6494 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006495{
Andre Guedes3655bba2013-10-30 19:01:40 -03006496 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6497 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006498 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006499
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006500 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6501 hdev);
6502
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006503 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006504 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006505 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006506
Andre Guedes3655bba2013-10-30 19:01:40 -03006507 cp = cmd->param;
6508
6509 if (bacmp(bdaddr, &cp->addr.bdaddr))
6510 return;
6511
6512 if (cp->addr.type != bdaddr_type)
6513 return;
6514
Johan Hedbergf5818c22014-12-05 13:36:02 +02006515 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006516 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006517}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006518
Marcel Holtmann445608d2013-10-06 23:55:48 -07006519void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6520 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006521{
6522 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006523
Johan Hedberg84c61d92014-08-01 11:13:30 +03006524 /* The connection is still in hci_conn_hash so test for 1
6525 * instead of 0 to know if this is the last one.
6526 */
6527 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6528 cancel_delayed_work(&hdev->power_off);
6529 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006530 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006531
Johan Hedberg4c659c32011-11-07 23:13:39 +02006532 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006533 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006534 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006535
Marcel Holtmann445608d2013-10-06 23:55:48 -07006536 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006537}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006538
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006539void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006540{
6541 struct mgmt_ev_pin_code_request ev;
6542
Johan Hedbergd8457692012-02-17 14:24:57 +02006543 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006544 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006545 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006546
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006547 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006548}
6549
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006550void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6551 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006552{
6553 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006554
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006555 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006556 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006557 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006558
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006559 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006560 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006561}
6562
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006563void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6564 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006565{
6566 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006567
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006568 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006569 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006570 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006571
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006572 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006573 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006574}
Johan Hedberga5c29682011-02-19 12:05:57 -03006575
Johan Hedberg744cf192011-11-08 20:40:14 +02006576int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006577 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006578 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006579{
6580 struct mgmt_ev_user_confirm_request ev;
6581
Johan Hedberg744cf192011-11-08 20:40:14 +02006582 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006583
Johan Hedberg272d90d2012-02-09 15:26:12 +02006584 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006585 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006586 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006587 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006588
Johan Hedberg744cf192011-11-08 20:40:14 +02006589 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006590 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006591}
6592
Johan Hedberg272d90d2012-02-09 15:26:12 +02006593int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006594 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006595{
6596 struct mgmt_ev_user_passkey_request ev;
6597
6598 BT_DBG("%s", hdev->name);
6599
Johan Hedberg272d90d2012-02-09 15:26:12 +02006600 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006601 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006602
6603 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006604 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006605}
6606
Brian Gix0df4c182011-11-16 13:53:13 -08006607static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006608 u8 link_type, u8 addr_type, u8 status,
6609 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006610{
6611 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006612
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006613 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006614 if (!cmd)
6615 return -ENOENT;
6616
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006617 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006618 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006619
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006620 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006621}
6622
Johan Hedberg744cf192011-11-08 20:40:14 +02006623int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006624 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006625{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006626 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006627 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006628}
6629
Johan Hedberg272d90d2012-02-09 15:26:12 +02006630int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006631 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006632{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006633 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006634 status,
6635 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006636}
Johan Hedberg2a611692011-02-19 12:06:00 -03006637
Brian Gix604086b2011-11-23 08:28:33 -08006638int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006639 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006640{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006641 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006643}
6644
Johan Hedberg272d90d2012-02-09 15:26:12 +02006645int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006646 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006647{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006648 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006649 status,
6650 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006651}
6652
Johan Hedberg92a25252012-09-06 18:39:26 +03006653int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6654 u8 link_type, u8 addr_type, u32 passkey,
6655 u8 entered)
6656{
6657 struct mgmt_ev_passkey_notify ev;
6658
6659 BT_DBG("%s", hdev->name);
6660
6661 bacpy(&ev.addr.bdaddr, bdaddr);
6662 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6663 ev.passkey = __cpu_to_le32(passkey);
6664 ev.entered = entered;
6665
6666 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6667}
6668
Johan Hedberge1e930f2014-09-08 17:09:49 -07006669void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006670{
6671 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006672 struct pending_cmd *cmd;
6673 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006674
Johan Hedberge1e930f2014-09-08 17:09:49 -07006675 bacpy(&ev.addr.bdaddr, &conn->dst);
6676 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6677 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006678
Johan Hedberge1e930f2014-09-08 17:09:49 -07006679 cmd = find_pairing(conn);
6680
6681 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6682 cmd ? cmd->sk : NULL);
6683
6684 if (cmd)
6685 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006686}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006687
Marcel Holtmann464996a2013-10-15 14:26:24 -07006688void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006689{
6690 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006691 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006692
6693 if (status) {
6694 u8 mgmt_err = mgmt_status(status);
6695 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006696 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006697 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006698 }
6699
Marcel Holtmann464996a2013-10-15 14:26:24 -07006700 if (test_bit(HCI_AUTH, &hdev->flags))
6701 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6702 &hdev->dev_flags);
6703 else
6704 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6705 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006706
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006707 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006708 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006709
Johan Hedberg47990ea2012-02-22 11:58:37 +02006710 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006711 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006712
6713 if (match.sk)
6714 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006715}
6716
Johan Hedberg890ea892013-03-15 17:06:52 -05006717static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006718{
Johan Hedberg890ea892013-03-15 17:06:52 -05006719 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006720 struct hci_cp_write_eir cp;
6721
Johan Hedberg976eb202012-10-24 21:12:01 +03006722 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006723 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006724
Johan Hedbergc80da272012-02-22 15:38:48 +02006725 memset(hdev->eir, 0, sizeof(hdev->eir));
6726
Johan Hedbergcacaf522012-02-21 00:52:42 +02006727 memset(&cp, 0, sizeof(cp));
6728
Johan Hedberg890ea892013-03-15 17:06:52 -05006729 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006730}
6731
Marcel Holtmann3e248562013-10-15 14:26:25 -07006732void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006733{
6734 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006735 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006736 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006737
6738 if (status) {
6739 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006740
6741 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006742 &hdev->dev_flags)) {
6743 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006744 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006745 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006746
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006747 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6748 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006749 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006750 }
6751
6752 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006753 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006754 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006755 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6756 if (!changed)
6757 changed = test_and_clear_bit(HCI_HS_ENABLED,
6758 &hdev->dev_flags);
6759 else
6760 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006761 }
6762
6763 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6764
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006765 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006766 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006767
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006768 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006769 sock_put(match.sk);
6770
Johan Hedberg890ea892013-03-15 17:06:52 -05006771 hci_req_init(&req, hdev);
6772
Johan Hedberg37699722014-06-24 14:00:27 +03006773 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6774 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6775 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6776 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006777 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006778 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006779 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006780 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006781
6782 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006783}
6784
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006785void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6786{
6787 struct cmd_lookup match = { NULL, hdev };
6788 bool changed = false;
6789
6790 if (status) {
6791 u8 mgmt_err = mgmt_status(status);
6792
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006793 if (enable) {
6794 if (test_and_clear_bit(HCI_SC_ENABLED,
6795 &hdev->dev_flags))
6796 new_settings(hdev, NULL);
6797 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6798 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006799
6800 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6801 cmd_status_rsp, &mgmt_err);
6802 return;
6803 }
6804
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006805 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006806 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006807 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006808 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006809 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6810 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006811
6812 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6813 settings_rsp, &match);
6814
6815 if (changed)
6816 new_settings(hdev, match.sk);
6817
6818 if (match.sk)
6819 sock_put(match.sk);
6820}
6821
Johan Hedberg92da6092013-03-15 17:06:55 -05006822static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006823{
6824 struct cmd_lookup *match = data;
6825
Johan Hedberg90e70452012-02-23 23:09:40 +02006826 if (match->sk == NULL) {
6827 match->sk = cmd->sk;
6828 sock_hold(match->sk);
6829 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006830}
6831
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006832void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6833 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006834{
Johan Hedberg90e70452012-02-23 23:09:40 +02006835 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006836
Johan Hedberg92da6092013-03-15 17:06:55 -05006837 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6838 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6839 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006840
6841 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006842 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6843 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006844
6845 if (match.sk)
6846 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006847}
6848
Marcel Holtmann7667da32013-10-15 14:26:27 -07006849void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006850{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006851 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006852 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006853
Johan Hedberg13928972013-03-15 17:07:00 -05006854 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006855 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006856
6857 memset(&ev, 0, sizeof(ev));
6858 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006859 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006860
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006861 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006862 if (!cmd) {
6863 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006864
Johan Hedberg13928972013-03-15 17:07:00 -05006865 /* If this is a HCI command related to powering on the
6866 * HCI dev don't send any mgmt signals.
6867 */
6868 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006869 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006870 }
6871
Marcel Holtmann7667da32013-10-15 14:26:27 -07006872 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6873 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006874}
Szymon Jancc35938b2011-03-22 13:12:21 +01006875
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006876void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006877 u8 *rand192, u8 *hash256, u8 *rand256,
6878 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006879{
6880 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006881
Johan Hedberg744cf192011-11-08 20:40:14 +02006882 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006883
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006884 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006885 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006886 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006887
6888 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006889 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6890 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006891 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006892 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006893 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006894
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006895 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006896 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006897
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006898 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006899 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006900
6901 cmd_complete(cmd->sk, hdev->id,
6902 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6903 &rp, sizeof(rp));
6904 } else {
6905 struct mgmt_rp_read_local_oob_data rp;
6906
6907 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006908 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006909
6910 cmd_complete(cmd->sk, hdev->id,
6911 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6912 &rp, sizeof(rp));
6913 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006914 }
6915
6916 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006917}
Johan Hedberge17acd42011-03-30 23:57:16 +03006918
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006919static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6920{
6921 int i;
6922
6923 for (i = 0; i < uuid_count; i++) {
6924 if (!memcmp(uuid, uuids[i], 16))
6925 return true;
6926 }
6927
6928 return false;
6929}
6930
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006931static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6932{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006933 u16 parsed = 0;
6934
6935 while (parsed < eir_len) {
6936 u8 field_len = eir[0];
6937 u8 uuid[16];
6938 int i;
6939
6940 if (field_len == 0)
6941 break;
6942
6943 if (eir_len - parsed < field_len + 1)
6944 break;
6945
6946 switch (eir[1]) {
6947 case EIR_UUID16_ALL:
6948 case EIR_UUID16_SOME:
6949 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02006950 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006951 uuid[13] = eir[i + 3];
6952 uuid[12] = eir[i + 2];
6953 if (has_uuid(uuid, uuid_count, uuids))
6954 return true;
6955 }
6956 break;
6957 case EIR_UUID32_ALL:
6958 case EIR_UUID32_SOME:
6959 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02006960 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006961 uuid[15] = eir[i + 5];
6962 uuid[14] = eir[i + 4];
6963 uuid[13] = eir[i + 3];
6964 uuid[12] = eir[i + 2];
6965 if (has_uuid(uuid, uuid_count, uuids))
6966 return true;
6967 }
6968 break;
6969 case EIR_UUID128_ALL:
6970 case EIR_UUID128_SOME:
6971 for (i = 0; i + 17 <= field_len; i += 16) {
6972 memcpy(uuid, eir + i + 2, 16);
6973 if (has_uuid(uuid, uuid_count, uuids))
6974 return true;
6975 }
6976 break;
6977 }
6978
6979 parsed += field_len + 1;
6980 eir += field_len + 1;
6981 }
6982
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006983 return false;
6984}
6985
Marcel Holtmann901801b2013-10-06 23:55:51 -07006986void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006987 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6988 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006989{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006990 char buf[512];
6991 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006992 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006993 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03006994
Johan Hedberg75ce2082014-07-02 22:42:01 +03006995 /* Don't send events for a non-kernel initiated discovery. With
6996 * LE one exception is if we have pend_le_reports > 0 in which
6997 * case we're doing passive scanning and want these events.
6998 */
6999 if (!hci_discovery_active(hdev)) {
7000 if (link_type == ACL_LINK)
7001 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007002 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007003 return;
7004 }
Andre Guedes12602d02013-04-30 15:29:40 -03007005
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007006 /* When using service discovery with a RSSI threshold, then check
7007 * if such a RSSI threshold is specified. If a RSSI threshold has
7008 * been specified, then all results with a RSSI smaller than the
7009 * RSSI threshold will be dropped.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007010 *
7011 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7012 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007013 */
7014 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Marcel Holtmannefb25132014-12-05 13:03:34 +01007015 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007016 return;
7017
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007018 /* Make sure that the buffer is big enough. The 5 extra bytes
7019 * are for the potential CoD field.
7020 */
7021 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007022 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007023
Johan Hedberg1dc06092012-01-15 21:01:23 +02007024 memset(buf, 0, sizeof(buf));
7025
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007026 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7027 * RSSI value was reported as 0 when not available. This behavior
7028 * is kept when using device discovery. This is required for full
7029 * backwards compatibility with the API.
7030 *
7031 * However when using service discovery, the value 127 will be
7032 * returned when the RSSI is not available.
7033 */
7034 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007035 rssi = 0;
7036
Johan Hedberg841c5642014-07-07 12:45:54 +03007037 bacpy(&ev->addr.bdaddr, bdaddr);
7038 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007039 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007040 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007041
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007042 if (eir_len > 0) {
7043 /* When using service discovery and a list of UUID is
7044 * provided, results with no matching UUID should be
7045 * dropped. In case there is a match the result is
7046 * kept and checking possible scan response data
7047 * will be skipped.
7048 */
7049 if (hdev->discovery.uuid_count > 0) {
7050 match = eir_has_uuids(eir, eir_len,
7051 hdev->discovery.uuid_count,
7052 hdev->discovery.uuids);
7053 if (!match)
7054 return;
7055 }
7056
7057 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007058 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007059 } else {
7060 /* When using service discovery and a list of UUID is
7061 * provided, results with empty EIR or advertising data
7062 * should be dropped since they do not match any UUID.
7063 */
7064 if (hdev->discovery.uuid_count > 0)
7065 return;
7066 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007067
Johan Hedberg1dc06092012-01-15 21:01:23 +02007068 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7069 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007070 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007071
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007072 if (scan_rsp_len > 0) {
7073 /* When using service discovery and a list of UUID is
7074 * provided, results with no matching UUID should be
7075 * dropped if there is no previous match from the
7076 * advertising data.
7077 */
7078 if (hdev->discovery.uuid_count > 0) {
7079 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7080 hdev->discovery.uuid_count,
7081 hdev->discovery.uuids))
7082 return;
7083 }
7084
7085 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007086 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007087 } else {
7088 /* When using service discovery and a list of UUID is
7089 * provided, results with empty scan response and no
7090 * previous matched advertising data should be dropped.
7091 */
7092 if (hdev->discovery.uuid_count > 0 && !match)
7093 return;
7094 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007095
7096 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7097 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007098
Marcel Holtmann901801b2013-10-06 23:55:51 -07007099 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007100}
Johan Hedberga88a9652011-03-30 13:18:12 +03007101
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007102void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7103 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007104{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007105 struct mgmt_ev_device_found *ev;
7106 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7107 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007108
Johan Hedbergb644ba32012-01-17 21:48:47 +02007109 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007110
Johan Hedbergb644ba32012-01-17 21:48:47 +02007111 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007112
Johan Hedbergb644ba32012-01-17 21:48:47 +02007113 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007114 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007115 ev->rssi = rssi;
7116
7117 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007118 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007119
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007120 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007121
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007122 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007123}
Johan Hedberg314b2382011-04-27 10:29:57 -04007124
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007125void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007126{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007127 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007128
Andre Guedes343fb142011-11-22 17:14:19 -03007129 BT_DBG("%s discovering %u", hdev->name, discovering);
7130
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007131 memset(&ev, 0, sizeof(ev));
7132 ev.type = hdev->discovery.type;
7133 ev.discovering = discovering;
7134
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007135 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007136}
Antti Julku5e762442011-08-25 16:48:02 +03007137
Marcel Holtmann5976e602013-10-06 04:08:14 -07007138static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7139{
7140 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007141}
7142
7143void mgmt_reenable_advertising(struct hci_dev *hdev)
7144{
7145 struct hci_request req;
7146
Marcel Holtmann5976e602013-10-06 04:08:14 -07007147 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7148 return;
7149
7150 hci_req_init(&req, hdev);
7151 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007152 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007153}