blob: 81b2886f64b8777ffa1ec23ad612599c35075a35 [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 Holtmannedd3896b2014-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-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 Hedbergf7b64e692010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Hedbergaee9b212012-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 Holtmannd603b76b2014-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 Holtmann5afeac12014-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 Hedbergf7b64e692010-12-13 21:07:06 +0200583
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200584 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
585 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586 settings |= MGMT_SETTING_CONFIGURATION;
587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588 return settings;
589}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_current_settings(struct hci_dev *hdev)
592{
593 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200594
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200595 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100596 settings |= MGMT_SETTING_POWERED;
597
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200598 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200599 settings |= MGMT_SETTING_CONNECTABLE;
600
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500601 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
602 settings |= MGMT_SETTING_FAST_CONNECTABLE;
603
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200604 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605 settings |= MGMT_SETTING_DISCOVERABLE;
606
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300607 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300608 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609
Johan Hedberg56f87902013-10-02 13:43:13 +0300610 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_BREDR;
612
Johan Hedberg06199cf2012-02-22 16:37:11 +0200613 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200615
Johan Hedberg47990ea2012-02-22 11:58:37 +0200616 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200618
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200621
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200622 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
623 settings |= MGMT_SETTING_HS;
624
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200625 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300626 settings |= MGMT_SETTING_ADVERTISING;
627
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800628 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
629 settings |= MGMT_SETTING_SECURE_CONN;
630
Johan Hedberg0663b292014-06-24 13:15:50 +0300631 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800632 settings |= MGMT_SETTING_DEBUG_KEYS;
633
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
635 settings |= MGMT_SETTING_PRIVACY;
636
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200637 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200638}
639
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300640#define PNP_INFO_SVCLASS_ID 0x1200
641
Johan Hedberg213202e2013-01-27 00:31:33 +0200642static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
643{
644 u8 *ptr = data, *uuids_start = NULL;
645 struct bt_uuid *uuid;
646
647 if (len < 4)
648 return ptr;
649
650 list_for_each_entry(uuid, &hdev->uuids, list) {
651 u16 uuid16;
652
653 if (uuid->size != 16)
654 continue;
655
656 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
657 if (uuid16 < 0x1100)
658 continue;
659
660 if (uuid16 == PNP_INFO_SVCLASS_ID)
661 continue;
662
663 if (!uuids_start) {
664 uuids_start = ptr;
665 uuids_start[0] = 1;
666 uuids_start[1] = EIR_UUID16_ALL;
667 ptr += 2;
668 }
669
670 /* Stop if not enough space to put next UUID */
671 if ((ptr - data) + sizeof(u16) > len) {
672 uuids_start[1] = EIR_UUID16_SOME;
673 break;
674 }
675
676 *ptr++ = (uuid16 & 0x00ff);
677 *ptr++ = (uuid16 & 0xff00) >> 8;
678 uuids_start[0] += sizeof(uuid16);
679 }
680
681 return ptr;
682}
683
Johan Hedbergcdf19632013-01-27 00:31:34 +0200684static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
685{
686 u8 *ptr = data, *uuids_start = NULL;
687 struct bt_uuid *uuid;
688
689 if (len < 6)
690 return ptr;
691
692 list_for_each_entry(uuid, &hdev->uuids, list) {
693 if (uuid->size != 32)
694 continue;
695
696 if (!uuids_start) {
697 uuids_start = ptr;
698 uuids_start[0] = 1;
699 uuids_start[1] = EIR_UUID32_ALL;
700 ptr += 2;
701 }
702
703 /* Stop if not enough space to put next UUID */
704 if ((ptr - data) + sizeof(u32) > len) {
705 uuids_start[1] = EIR_UUID32_SOME;
706 break;
707 }
708
709 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
710 ptr += sizeof(u32);
711 uuids_start[0] += sizeof(u32);
712 }
713
714 return ptr;
715}
716
Johan Hedbergc00d5752013-01-27 00:31:35 +0200717static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
718{
719 u8 *ptr = data, *uuids_start = NULL;
720 struct bt_uuid *uuid;
721
722 if (len < 18)
723 return ptr;
724
725 list_for_each_entry(uuid, &hdev->uuids, list) {
726 if (uuid->size != 128)
727 continue;
728
729 if (!uuids_start) {
730 uuids_start = ptr;
731 uuids_start[0] = 1;
732 uuids_start[1] = EIR_UUID128_ALL;
733 ptr += 2;
734 }
735
736 /* Stop if not enough space to put next UUID */
737 if ((ptr - data) + 16 > len) {
738 uuids_start[1] = EIR_UUID128_SOME;
739 break;
740 }
741
742 memcpy(ptr, uuid->uuid, 16);
743 ptr += 16;
744 uuids_start[0] += 16;
745 }
746
747 return ptr;
748}
749
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300750static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
751{
752 struct pending_cmd *cmd;
753
754 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
755 if (cmd->opcode == opcode)
756 return cmd;
757 }
758
759 return NULL;
760}
761
Johan Hedberg95868422014-06-28 17:54:07 +0300762static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
763 struct hci_dev *hdev,
764 const void *data)
765{
766 struct pending_cmd *cmd;
767
768 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
769 if (cmd->user_data != data)
770 continue;
771 if (cmd->opcode == opcode)
772 return cmd;
773 }
774
775 return NULL;
776}
777
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700778static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
779{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700780 u8 ad_len = 0;
781 size_t name_len;
782
783 name_len = strlen(hdev->dev_name);
784 if (name_len > 0) {
785 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
786
787 if (name_len > max_len) {
788 name_len = max_len;
789 ptr[1] = EIR_NAME_SHORT;
790 } else
791 ptr[1] = EIR_NAME_COMPLETE;
792
793 ptr[0] = name_len + 1;
794
795 memcpy(ptr + 2, hdev->dev_name, name_len);
796
797 ad_len += (name_len + 2);
798 ptr += (name_len + 2);
799 }
800
801 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802}
803
804static void update_scan_rsp_data(struct hci_request *req)
805{
806 struct hci_dev *hdev = req->hdev;
807 struct hci_cp_le_set_scan_rsp_data cp;
808 u8 len;
809
Johan Hedberg7751ef12013-10-19 23:38:15 +0300810 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811 return;
812
813 memset(&cp, 0, sizeof(cp));
814
815 len = create_scan_rsp_data(hdev, cp.data);
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 if (hdev->scan_rsp_data_len == len &&
818 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819 return;
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
822 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823
824 cp.length = len;
825
826 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
827}
828
Johan Hedberg9a43e252013-10-20 19:00:07 +0300829static u8 get_adv_discov_flags(struct hci_dev *hdev)
830{
831 struct pending_cmd *cmd;
832
833 /* If there's a pending mgmt command the flags will not yet have
834 * their final values, so check for this first.
835 */
836 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
837 if (cmd) {
838 struct mgmt_mode *cp = cmd->param;
839 if (cp->val == 0x01)
840 return LE_AD_GENERAL;
841 else if (cp->val == 0x02)
842 return LE_AD_LIMITED;
843 } else {
844 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_LIMITED;
846 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
847 return LE_AD_GENERAL;
848 }
849
850 return 0;
851}
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854{
855 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberg9a43e252013-10-20 19:00:07 +0300857 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
Johan Hedberge8340042014-01-30 11:16:50 -0800859 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
862 if (flags) {
863 BT_DBG("adv flags 0x%02x", flags);
864
865 ptr[0] = 2;
866 ptr[1] = EIR_FLAGS;
867 ptr[2] = flags;
868
869 ad_len += 3;
870 ptr += 3;
871 }
872
873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
874 ptr[0] = 2;
875 ptr[1] = EIR_TX_POWER;
876 ptr[2] = (u8) hdev->adv_tx_power;
877
878 ad_len += 3;
879 ptr += 3;
880 }
881
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882 return ad_len;
883}
884
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700885static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886{
887 struct hci_dev *hdev = req->hdev;
888 struct hci_cp_le_set_adv_data cp;
889 u8 len;
890
Johan Hedberg10994ce2013-10-19 23:38:16 +0300891 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700892 return;
893
894 memset(&cp, 0, sizeof(cp));
895
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700896 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700897
898 if (hdev->adv_data_len == len &&
899 memcmp(cp.data, hdev->adv_data, len) == 0)
900 return;
901
902 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
903 hdev->adv_data_len = len;
904
905 cp.length = len;
906
907 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
908}
909
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300910int mgmt_update_adv_data(struct hci_dev *hdev)
911{
912 struct hci_request req;
913
914 hci_req_init(&req, hdev);
915 update_adv_data(&req);
916
917 return hci_req_run(&req, NULL);
918}
919
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920static void create_eir(struct hci_dev *hdev, u8 *data)
921{
922 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923 size_t name_len;
924
925 name_len = strlen(hdev->dev_name);
926
927 if (name_len > 0) {
928 /* EIR Data type */
929 if (name_len > 48) {
930 name_len = 48;
931 ptr[1] = EIR_NAME_SHORT;
932 } else
933 ptr[1] = EIR_NAME_COMPLETE;
934
935 /* EIR Data length */
936 ptr[0] = name_len + 1;
937
938 memcpy(ptr + 2, hdev->dev_name, name_len);
939
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300940 ptr += (name_len + 2);
941 }
942
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100943 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr[0] = 2;
945 ptr[1] = EIR_TX_POWER;
946 ptr[2] = (u8) hdev->inq_tx_power;
947
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr += 3;
949 }
950
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700951 if (hdev->devid_source > 0) {
952 ptr[0] = 9;
953 ptr[1] = EIR_DEVICE_ID;
954
955 put_unaligned_le16(hdev->devid_source, ptr + 2);
956 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
957 put_unaligned_le16(hdev->devid_product, ptr + 6);
958 put_unaligned_le16(hdev->devid_version, ptr + 8);
959
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700960 ptr += 10;
961 }
962
Johan Hedberg213202e2013-01-27 00:31:33 +0200963 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200964 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200965 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966}
967
Johan Hedberg890ea892013-03-15 17:06:52 -0500968static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969{
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300971 struct hci_cp_write_eir cp;
972
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200973 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200975
Johan Hedberg976eb202012-10-24 21:12:01 +0300976 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200979 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200982 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
985 memset(&cp, 0, sizeof(cp));
986
987 create_eir(hdev, cp.data);
988
989 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991
992 memcpy(hdev->eir, cp.data, sizeof(cp.data));
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995}
996
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997static u8 get_service_classes(struct hci_dev *hdev)
998{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 val = 0;
1001
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004
1005 return val;
1006}
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009{
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001011 u8 cod[3];
1012
1013 BT_DBG("%s", hdev->name);
1014
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001015 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001017
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001018 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1019 return;
1020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001021 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001022 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
1024 cod[0] = hdev->minor_class;
1025 cod[1] = hdev->major_class;
1026 cod[2] = get_service_classes(hdev);
1027
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001028 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1029 cod[1] |= 0x20;
1030
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035}
1036
Johan Hedberga4858cb2014-02-25 19:56:31 +02001037static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038{
1039 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040
1041 /* If there's a pending mgmt command the flag will not yet have
1042 * it's final value, so check for this first.
1043 */
1044 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1045 if (cmd) {
1046 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048 }
1049
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051}
1052
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001053static void disable_advertising(struct hci_request *req)
1054{
1055 u8 enable = 0x00;
1056
1057 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1058}
1059
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001060static void enable_advertising(struct hci_request *req)
1061{
1062 struct hci_dev *hdev = req->hdev;
1063 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001064 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001066
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001067 if (hci_conn_num(hdev, LE_LINK) > 0)
1068 return;
1069
1070 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1071 disable_advertising(req);
1072
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001073 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001074 * hci_update_random_address knows that it's safe to go ahead
1075 * and write a new random address. The flag will be set back on
1076 * as soon as the SET_ADV_ENABLE HCI command completes.
1077 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001078 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001081
Johan Hedberga4858cb2014-02-25 19:56:31 +02001082 /* Set require_privacy to true only when non-connectable
1083 * advertising is used. In that case it is fine to use a
1084 * non-resolvable private address.
1085 */
1086 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001087 return;
1088
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001089 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001090 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1091 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001092 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001093 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001094 cp.channel_map = hdev->le_adv_channel_map;
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1097
1098 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1099}
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101static void service_cache_off(struct work_struct *work)
1102{
1103 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001104 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001107 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 return;
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 hci_req_init(&req, hdev);
1111
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 hci_dev_lock(hdev);
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 update_eir(&req);
1115 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116
1117 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001118
1119 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120}
1121
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122static void rpa_expired(struct work_struct *work)
1123{
1124 struct hci_dev *hdev = container_of(work, struct hci_dev,
1125 rpa_expired.work);
1126 struct hci_request req;
1127
1128 BT_DBG("");
1129
1130 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1131
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001132 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001133 return;
1134
1135 /* The generation of a new RPA and programming it into the
1136 * controller happens in the enable_advertising() function.
1137 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 hci_req_run(&req, NULL);
1141}
1142
Johan Hedberg6a919082012-02-28 06:17:26 +02001143static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001144{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001146 return;
1147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001149 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 /* Non-mgmt controlled devices get this bit set
1152 * implicitly so that pairing works for them, however
1153 * for mgmt we require user-space to explicitly enable
1154 * it
1155 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001156 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001157}
1158
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001159static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001161{
1162 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 memset(&rp, 0, sizeof(rp));
1169
Johan Hedberg03811012010-12-08 00:21:06 +02001170 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001173 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1176 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1177
1178 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
1180 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001181 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001183 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001184
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001185 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001187}
1188
1189static void mgmt_pending_free(struct pending_cmd *cmd)
1190{
1191 sock_put(cmd->sk);
1192 kfree(cmd->param);
1193 kfree(cmd);
1194}
1195
1196static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 struct hci_dev *hdev, void *data,
1198 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001199{
1200 struct pending_cmd *cmd;
1201
Johan Hedbergfca20012014-06-28 17:54:05 +03001202 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 if (!cmd)
1204 return NULL;
1205
1206 cmd->opcode = opcode;
1207 cmd->index = hdev->id;
1208
Johan Hedberg323b0b82014-12-05 13:36:01 +02001209 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001210 if (!cmd->param) {
1211 kfree(cmd);
1212 return NULL;
1213 }
1214
Johan Hedberg323b0b82014-12-05 13:36:01 +02001215 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b212012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan 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 Hedberge6fe7982013-10-02 15:45:22 +03001495static u8 mgmt_bredr_support(struct hci_dev *hdev)
1496{
1497 if (!lmp_bredr_capable(hdev))
1498 return MGMT_STATUS_NOT_SUPPORTED;
1499 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1500 return MGMT_STATUS_REJECTED;
1501 else
1502 return MGMT_STATUS_SUCCESS;
1503}
1504
1505static u8 mgmt_le_support(struct hci_dev *hdev)
1506{
1507 if (!lmp_le_capable(hdev))
1508 return MGMT_STATUS_NOT_SUPPORTED;
1509 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1510 return MGMT_STATUS_REJECTED;
1511 else
1512 return MGMT_STATUS_SUCCESS;
1513}
1514
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001515static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1516{
1517 struct pending_cmd *cmd;
1518 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001519 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001520 bool changed;
1521
1522 BT_DBG("status 0x%02x", status);
1523
1524 hci_dev_lock(hdev);
1525
1526 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1527 if (!cmd)
1528 goto unlock;
1529
1530 if (status) {
1531 u8 mgmt_err = mgmt_status(status);
1532 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001533 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001534 goto remove_cmd;
1535 }
1536
1537 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001538 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001539 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1540 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001541
1542 if (hdev->discov_timeout > 0) {
1543 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1544 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1545 to);
1546 }
1547 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001548 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1549 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001550 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001551
1552 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1553
1554 if (changed)
1555 new_settings(hdev, cmd->sk);
1556
Marcel Holtmann970ba522013-10-15 06:33:57 -07001557 /* When the discoverable mode gets changed, make sure
1558 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001559 * bit correctly set. Also update page scan based on whitelist
1560 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001561 */
1562 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001563 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001564 update_class(&req);
1565 hci_req_run(&req, NULL);
1566
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001567remove_cmd:
1568 mgmt_pending_remove(cmd);
1569
1570unlock:
1571 hci_dev_unlock(hdev);
1572}
1573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001574static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001575 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001576{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001577 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001578 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001579 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001580 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001581 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001582 int err;
1583
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001584 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001585
Johan Hedberg9a43e252013-10-20 19:00:07 +03001586 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1587 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001588 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001589 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001590
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001591 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001592 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1593 MGMT_STATUS_INVALID_PARAMS);
1594
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001595 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001596
1597 /* Disabling discoverable requires that no timeout is set,
1598 * and enabling limited discoverable requires a timeout.
1599 */
1600 if ((cp->val == 0x00 && timeout > 0) ||
1601 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001602 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001603 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001604
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001605 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001606
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001607 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001610 goto failed;
1611 }
1612
1613 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001614 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001615 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001616 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001617 goto failed;
1618 }
1619
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001620 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
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_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001623 goto failed;
1624 }
1625
1626 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001627 bool changed = false;
1628
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001629 /* Setting limited discoverable when powered off is
1630 * not a valid operation since it requires a timeout
1631 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1632 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1634 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1635 changed = true;
1636 }
1637
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001638 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (err < 0)
1640 goto failed;
1641
1642 if (changed)
1643 err = new_settings(hdev, sk);
1644
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001645 goto failed;
1646 }
1647
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001648 /* If the current mode is the same, then just update the timeout
1649 * value with the new value. And if only the timeout gets updated,
1650 * then no need for any HCI transactions.
1651 */
1652 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1653 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1654 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001655 cancel_delayed_work(&hdev->discov_off);
1656 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001657
Marcel Holtmann36261542013-10-15 08:28:51 -07001658 if (cp->val && hdev->discov_timeout > 0) {
1659 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001660 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001662 }
1663
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001664 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001665 goto failed;
1666 }
1667
1668 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1669 if (!cmd) {
1670 err = -ENOMEM;
1671 goto failed;
1672 }
1673
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001674 /* Cancel any potential discoverable timeout that might be
1675 * still active and store new timeout value. The arming of
1676 * the timeout happens in the complete handler.
1677 */
1678 cancel_delayed_work(&hdev->discov_off);
1679 hdev->discov_timeout = timeout;
1680
Johan Hedbergb456f872013-10-19 23:38:22 +03001681 /* Limited discoverable mode */
1682 if (cp->val == 0x02)
1683 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1684 else
1685 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1686
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001687 hci_req_init(&req, hdev);
1688
Johan Hedberg9a43e252013-10-20 19:00:07 +03001689 /* The procedure for LE-only controllers is much simpler - just
1690 * update the advertising data.
1691 */
1692 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1693 goto update_ad;
1694
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001695 scan = SCAN_PAGE;
1696
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001697 if (cp->val) {
1698 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001699
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001700 if (cp->val == 0x02) {
1701 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001702 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1704 hci_cp.iac_lap[1] = 0x8b;
1705 hci_cp.iac_lap[2] = 0x9e;
1706 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1707 hci_cp.iac_lap[4] = 0x8b;
1708 hci_cp.iac_lap[5] = 0x9e;
1709 } else {
1710 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001711 hci_cp.num_iac = 1;
1712 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[1] = 0x8b;
1714 hci_cp.iac_lap[2] = 0x9e;
1715 }
1716
1717 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1718 (hci_cp.num_iac * 3) + 1, &hci_cp);
1719
1720 scan |= SCAN_INQUIRY;
1721 } else {
1722 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1723 }
1724
1725 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001726
Johan Hedberg9a43e252013-10-20 19:00:07 +03001727update_ad:
1728 update_adv_data(&req);
1729
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001730 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001731 if (err < 0)
1732 mgmt_pending_remove(cmd);
1733
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001734failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001735 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001736 return err;
1737}
1738
Johan Hedberg406d7802013-03-15 17:07:09 -05001739static void write_fast_connectable(struct hci_request *req, bool enable)
1740{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001741 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001742 struct hci_cp_write_page_scan_activity acp;
1743 u8 type;
1744
Johan Hedberg547003b2013-10-21 16:51:53 +03001745 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1746 return;
1747
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001748 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1749 return;
1750
Johan Hedberg406d7802013-03-15 17:07:09 -05001751 if (enable) {
1752 type = PAGE_SCAN_TYPE_INTERLACED;
1753
1754 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001755 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001756 } else {
1757 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1758
1759 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001760 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001761 }
1762
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001763 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001764
Johan Hedbergbd98b992013-03-15 17:07:13 -05001765 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1766 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1767 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1768 sizeof(acp), &acp);
1769
1770 if (hdev->page_scan_type != type)
1771 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001772}
1773
Johan Hedberg2b76f452013-03-15 17:07:04 -05001774static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1775{
1776 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001777 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001778 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001779
1780 BT_DBG("status 0x%02x", status);
1781
1782 hci_dev_lock(hdev);
1783
1784 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1785 if (!cmd)
1786 goto unlock;
1787
Johan Hedberg37438c12013-10-14 16:20:05 +03001788 if (status) {
1789 u8 mgmt_err = mgmt_status(status);
1790 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1791 goto remove_cmd;
1792 }
1793
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001794 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001795 if (cp->val) {
1796 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1797 &hdev->dev_flags);
1798 discov_changed = false;
1799 } else {
1800 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1801 &hdev->dev_flags);
1802 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1803 &hdev->dev_flags);
1804 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001805
Johan Hedberg2b76f452013-03-15 17:07:04 -05001806 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1807
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001808 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001809 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001810 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001811 if (discov_changed)
1812 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001813 hci_update_background_scan(hdev);
1814 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815
Johan Hedberg37438c12013-10-14 16:20:05 +03001816remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001817 mgmt_pending_remove(cmd);
1818
1819unlock:
1820 hci_dev_unlock(hdev);
1821}
1822
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001823static int set_connectable_update_settings(struct hci_dev *hdev,
1824 struct sock *sk, u8 val)
1825{
1826 bool changed = false;
1827 int err;
1828
1829 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1830 changed = true;
1831
1832 if (val) {
1833 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1834 } else {
1835 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1836 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1837 }
1838
1839 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1840 if (err < 0)
1841 return err;
1842
Johan Hedberg562064e2014-07-08 16:35:34 +03001843 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001844 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001845 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001846 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001847 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001848
1849 return 0;
1850}
1851
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001852static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001853 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001854{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001855 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001856 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001857 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001858 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001859 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001860
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001861 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001862
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001863 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1864 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001865 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001866 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001867
Johan Hedberga7e80f22013-01-09 16:05:19 +02001868 if (cp->val != 0x00 && cp->val != 0x01)
1869 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1870 MGMT_STATUS_INVALID_PARAMS);
1871
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001872 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001873
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001874 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001875 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001876 goto failed;
1877 }
1878
1879 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001880 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001881 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001882 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001883 goto failed;
1884 }
1885
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001886 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1887 if (!cmd) {
1888 err = -ENOMEM;
1889 goto failed;
1890 }
1891
Johan Hedberg2b76f452013-03-15 17:07:04 -05001892 hci_req_init(&req, hdev);
1893
Johan Hedberg9a43e252013-10-20 19:00:07 +03001894 /* If BR/EDR is not enabled and we disable advertising as a
1895 * by-product of disabling connectable, we need to update the
1896 * advertising flags.
1897 */
1898 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1899 if (!cp->val) {
1900 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1901 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1902 }
1903 update_adv_data(&req);
1904 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001905 if (cp->val) {
1906 scan = SCAN_PAGE;
1907 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001908 /* If we don't have any whitelist entries just
1909 * disable all scanning. If there are entries
1910 * and we had both page and inquiry scanning
1911 * enabled then fall back to only page scanning.
1912 * Otherwise no changes are needed.
1913 */
1914 if (list_empty(&hdev->whitelist))
1915 scan = SCAN_DISABLED;
1916 else if (test_bit(HCI_ISCAN, &hdev->flags))
1917 scan = SCAN_PAGE;
1918 else
1919 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001920
1921 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001922 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001923 cancel_delayed_work(&hdev->discov_off);
1924 }
1925
1926 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1927 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001928
Johan Hedberg3bd27242014-07-28 20:53:58 +03001929no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001930 /* If we're going from non-connectable to connectable or
1931 * vice-versa when fast connectable is enabled ensure that fast
1932 * connectable gets disabled. write_fast_connectable won't do
1933 * anything if the page scan parameters are already what they
1934 * should be.
1935 */
1936 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001937 write_fast_connectable(&req, false);
1938
Johan Hedberge8b12022014-07-10 10:51:27 +03001939 /* Update the advertising parameters if necessary */
1940 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001941 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001942
Johan Hedberg2b76f452013-03-15 17:07:04 -05001943 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001944 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001945 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001946 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001947 err = set_connectable_update_settings(hdev, sk,
1948 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001949 goto failed;
1950 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951
1952failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001953 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001954 return err;
1955}
1956
Johan Hedbergb2939472014-07-30 09:22:23 +03001957static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001958 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001959{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001960 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001961 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001962 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001963
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001964 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001965
Johan Hedberga7e80f22013-01-09 16:05:19 +02001966 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001967 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001968 MGMT_STATUS_INVALID_PARAMS);
1969
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001970 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
1972 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001973 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001974 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001975 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001976
Johan Hedbergb2939472014-07-30 09:22:23 +03001977 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001978 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001979 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980
Marcel Holtmann55594352013-10-06 16:11:57 -07001981 if (changed)
1982 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001983
Marcel Holtmann55594352013-10-06 16:11:57 -07001984unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001985 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986 return err;
1987}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001988
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001989static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1990 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001991{
1992 struct mgmt_mode *cp = data;
1993 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03001994 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001995 int err;
1996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001997 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001998
Johan Hedberge6fe7982013-10-02 15:45:22 +03001999 status = mgmt_bredr_support(hdev);
2000 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002001 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002002 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002003
Johan Hedberga7e80f22013-01-09 16:05:19 +02002004 if (cp->val != 0x00 && cp->val != 0x01)
2005 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2006 MGMT_STATUS_INVALID_PARAMS);
2007
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002008 hci_dev_lock(hdev);
2009
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002010 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002011 bool changed = false;
2012
2013 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002014 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002015 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2016 changed = true;
2017 }
2018
2019 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2020 if (err < 0)
2021 goto failed;
2022
2023 if (changed)
2024 err = new_settings(hdev, sk);
2025
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002026 goto failed;
2027 }
2028
2029 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002030 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002031 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 val = !!cp->val;
2036
2037 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2038 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2039 goto failed;
2040 }
2041
2042 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2043 if (!cmd) {
2044 err = -ENOMEM;
2045 goto failed;
2046 }
2047
2048 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2049 if (err < 0) {
2050 mgmt_pending_remove(cmd);
2051 goto failed;
2052 }
2053
2054failed:
2055 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002056 return err;
2057}
2058
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002059static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002060{
2061 struct mgmt_mode *cp = data;
2062 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002063 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002064 int err;
2065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002066 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002067
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002068 status = mgmt_bredr_support(hdev);
2069 if (status)
2070 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2071
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002072 if (!lmp_ssp_capable(hdev))
2073 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2074 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002075
Johan Hedberga7e80f22013-01-09 16:05:19 +02002076 if (cp->val != 0x00 && cp->val != 0x01)
2077 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2078 MGMT_STATUS_INVALID_PARAMS);
2079
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002080 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002081
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002082 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002083 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002084
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002085 if (cp->val) {
2086 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2087 &hdev->dev_flags);
2088 } else {
2089 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2090 &hdev->dev_flags);
2091 if (!changed)
2092 changed = test_and_clear_bit(HCI_HS_ENABLED,
2093 &hdev->dev_flags);
2094 else
2095 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002096 }
2097
2098 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2099 if (err < 0)
2100 goto failed;
2101
2102 if (changed)
2103 err = new_settings(hdev, sk);
2104
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002105 goto failed;
2106 }
2107
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002108 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2109 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002110 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2111 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002112 goto failed;
2113 }
2114
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002115 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002116 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2117 goto failed;
2118 }
2119
2120 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2121 if (!cmd) {
2122 err = -ENOMEM;
2123 goto failed;
2124 }
2125
Johan Hedberg37699722014-06-24 14:00:27 +03002126 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2127 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2128 sizeof(cp->val), &cp->val);
2129
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002130 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002131 if (err < 0) {
2132 mgmt_pending_remove(cmd);
2133 goto failed;
2134 }
2135
2136failed:
2137 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002138 return err;
2139}
2140
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002141static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002142{
2143 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002144 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002145 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002146 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002147
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002148 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002149
Johan Hedberge6fe7982013-10-02 15:45:22 +03002150 status = mgmt_bredr_support(hdev);
2151 if (status)
2152 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002154 if (!lmp_ssp_capable(hdev))
2155 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2156 MGMT_STATUS_NOT_SUPPORTED);
2157
2158 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2159 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2160 MGMT_STATUS_REJECTED);
2161
Johan Hedberga7e80f22013-01-09 16:05:19 +02002162 if (cp->val != 0x00 && cp->val != 0x01)
2163 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2164 MGMT_STATUS_INVALID_PARAMS);
2165
Marcel Holtmannee392692013-10-01 22:59:23 -07002166 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002167
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002168 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002169 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002170 } else {
2171 if (hdev_is_powered(hdev)) {
2172 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2173 MGMT_STATUS_REJECTED);
2174 goto unlock;
2175 }
2176
Marcel Holtmannee392692013-10-01 22:59:23 -07002177 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002178 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002179
2180 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2181 if (err < 0)
2182 goto unlock;
2183
2184 if (changed)
2185 err = new_settings(hdev, sk);
2186
2187unlock:
2188 hci_dev_unlock(hdev);
2189 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002190}
2191
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002192static void le_enable_complete(struct hci_dev *hdev, u8 status)
2193{
2194 struct cmd_lookup match = { NULL, hdev };
2195
2196 if (status) {
2197 u8 mgmt_err = mgmt_status(status);
2198
2199 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2200 &mgmt_err);
2201 return;
2202 }
2203
2204 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2205
2206 new_settings(hdev, match.sk);
2207
2208 if (match.sk)
2209 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002210
2211 /* Make sure the controller has a good default for
2212 * advertising data. Restrict the update to when LE
2213 * has actually been enabled. During power on, the
2214 * update in powered_update_hci will take care of it.
2215 */
2216 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2217 struct hci_request req;
2218
2219 hci_dev_lock(hdev);
2220
2221 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002222 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002223 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002224 hci_req_run(&req, NULL);
2225
Johan Hedberga70f4b52014-07-07 15:19:50 +03002226 hci_update_background_scan(hdev);
2227
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002228 hci_dev_unlock(hdev);
2229 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002230}
2231
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002232static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002233{
2234 struct mgmt_mode *cp = data;
2235 struct hci_cp_write_le_host_supported hci_cp;
2236 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002238 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002239 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002241 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002242
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002243 if (!lmp_le_capable(hdev))
2244 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2245 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002246
Johan Hedberga7e80f22013-01-09 16:05:19 +02002247 if (cp->val != 0x00 && cp->val != 0x01)
2248 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2249 MGMT_STATUS_INVALID_PARAMS);
2250
Johan Hedbergc73eee92013-04-19 18:35:21 +03002251 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002252 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002253 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2254 MGMT_STATUS_REJECTED);
2255
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002256 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002257
2258 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002259 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002260
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002261 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002262 bool changed = false;
2263
2264 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2265 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2266 changed = true;
2267 }
2268
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002269 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2270 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002271 changed = true;
2272 }
2273
Johan Hedberg06199cf2012-02-22 16:37:11 +02002274 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2275 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002276 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002277
2278 if (changed)
2279 err = new_settings(hdev, sk);
2280
Johan Hedberg1de028c2012-02-29 19:55:35 -08002281 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002282 }
2283
Johan Hedberg4375f102013-09-25 13:26:10 +03002284 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2285 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002286 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002287 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002288 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002289 }
2290
2291 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2292 if (!cmd) {
2293 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002297 hci_req_init(&req, hdev);
2298
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299 memset(&hci_cp, 0, sizeof(hci_cp));
2300
2301 if (val) {
2302 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002303 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002304 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002305 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002306 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002307 }
2308
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002309 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2310 &hci_cp);
2311
2312 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302313 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002315
Johan Hedberg1de028c2012-02-29 19:55:35 -08002316unlock:
2317 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002318 return err;
2319}
2320
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002321/* This is a helper function to test for pending mgmt commands that can
2322 * cause CoD or EIR HCI commands. We can only allow one such pending
2323 * mgmt command at a time since otherwise we cannot easily track what
2324 * the current values are, will be, and based on that calculate if a new
2325 * HCI command needs to be sent and if yes with what value.
2326 */
2327static bool pending_eir_or_class(struct hci_dev *hdev)
2328{
2329 struct pending_cmd *cmd;
2330
2331 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2332 switch (cmd->opcode) {
2333 case MGMT_OP_ADD_UUID:
2334 case MGMT_OP_REMOVE_UUID:
2335 case MGMT_OP_SET_DEV_CLASS:
2336 case MGMT_OP_SET_POWERED:
2337 return true;
2338 }
2339 }
2340
2341 return false;
2342}
2343
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002344static const u8 bluetooth_base_uuid[] = {
2345 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2346 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2347};
2348
2349static u8 get_uuid_size(const u8 *uuid)
2350{
2351 u32 val;
2352
2353 if (memcmp(uuid, bluetooth_base_uuid, 12))
2354 return 128;
2355
2356 val = get_unaligned_le32(&uuid[12]);
2357 if (val > 0xffff)
2358 return 32;
2359
2360 return 16;
2361}
2362
Johan Hedberg92da6092013-03-15 17:06:55 -05002363static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2364{
2365 struct pending_cmd *cmd;
2366
2367 hci_dev_lock(hdev);
2368
2369 cmd = mgmt_pending_find(mgmt_op, hdev);
2370 if (!cmd)
2371 goto unlock;
2372
2373 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2374 hdev->dev_class, 3);
2375
2376 mgmt_pending_remove(cmd);
2377
2378unlock:
2379 hci_dev_unlock(hdev);
2380}
2381
2382static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2383{
2384 BT_DBG("status 0x%02x", status);
2385
2386 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2387}
2388
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002389static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002390{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002391 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002392 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002393 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002394 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002395 int err;
2396
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002397 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002398
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002399 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002401 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002402 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002403 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002404 goto failed;
2405 }
2406
Andre Guedes92c4c202012-06-07 19:05:44 -03002407 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002408 if (!uuid) {
2409 err = -ENOMEM;
2410 goto failed;
2411 }
2412
2413 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002414 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002415 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002416
Johan Hedbergde66aa62013-01-27 00:31:27 +02002417 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002418
Johan Hedberg890ea892013-03-15 17:06:52 -05002419 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420
Johan Hedberg890ea892013-03-15 17:06:52 -05002421 update_class(&req);
2422 update_eir(&req);
2423
Johan Hedberg92da6092013-03-15 17:06:55 -05002424 err = hci_req_run(&req, add_uuid_complete);
2425 if (err < 0) {
2426 if (err != -ENODATA)
2427 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002428
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002429 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002430 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002431 goto failed;
2432 }
2433
2434 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002435 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002436 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002437 goto failed;
2438 }
2439
2440 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002441
2442failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002443 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002444 return err;
2445}
2446
Johan Hedberg24b78d02012-02-23 23:24:30 +02002447static bool enable_service_cache(struct hci_dev *hdev)
2448{
2449 if (!hdev_is_powered(hdev))
2450 return false;
2451
2452 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002453 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2454 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002455 return true;
2456 }
2457
2458 return false;
2459}
2460
Johan Hedberg92da6092013-03-15 17:06:55 -05002461static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2462{
2463 BT_DBG("status 0x%02x", status);
2464
2465 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2466}
2467
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002468static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002469 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002470{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002471 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002472 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002473 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002474 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 -05002475 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476 int err, found;
2477
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002478 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002479
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002480 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002482 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002483 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002484 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002485 goto unlock;
2486 }
2487
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002488 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002489 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002490
Johan Hedberg24b78d02012-02-23 23:24:30 +02002491 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002492 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002493 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002494 goto unlock;
2495 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg9246a862012-02-23 21:33:16 +02002497 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002498 }
2499
2500 found = 0;
2501
Johan Hedberg056341c2013-01-27 00:31:30 +02002502 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002503 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2504 continue;
2505
2506 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002507 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002508 found++;
2509 }
2510
2511 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002512 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002513 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 goto unlock;
2515 }
2516
Johan Hedberg9246a862012-02-23 21:33:16 +02002517update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002518 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002519
Johan Hedberg890ea892013-03-15 17:06:52 -05002520 update_class(&req);
2521 update_eir(&req);
2522
Johan Hedberg92da6092013-03-15 17:06:55 -05002523 err = hci_req_run(&req, remove_uuid_complete);
2524 if (err < 0) {
2525 if (err != -ENODATA)
2526 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002527
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002528 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002529 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002530 goto unlock;
2531 }
2532
2533 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002534 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002535 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002536 goto unlock;
2537 }
2538
2539 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002540
2541unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002542 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002543 return err;
2544}
2545
Johan Hedberg92da6092013-03-15 17:06:55 -05002546static void set_class_complete(struct hci_dev *hdev, u8 status)
2547{
2548 BT_DBG("status 0x%02x", status);
2549
2550 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2551}
2552
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002553static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002554 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002555{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002556 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002557 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559 int err;
2560
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002561 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002562
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002563 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002564 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2565 MGMT_STATUS_NOT_SUPPORTED);
2566
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002567 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002569 if (pending_eir_or_class(hdev)) {
2570 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_BUSY);
2572 goto unlock;
2573 }
2574
2575 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_INVALID_PARAMS);
2578 goto unlock;
2579 }
2580
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002581 hdev->major_class = cp->major;
2582 hdev->minor_class = cp->minor;
2583
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002584 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002585 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002586 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002587 goto unlock;
2588 }
2589
Johan Hedberg890ea892013-03-15 17:06:52 -05002590 hci_req_init(&req, hdev);
2591
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002592 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002593 hci_dev_unlock(hdev);
2594 cancel_delayed_work_sync(&hdev->service_cache);
2595 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002597 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002598
Johan Hedberg890ea892013-03-15 17:06:52 -05002599 update_class(&req);
2600
Johan Hedberg92da6092013-03-15 17:06:55 -05002601 err = hci_req_run(&req, set_class_complete);
2602 if (err < 0) {
2603 if (err != -ENODATA)
2604 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002605
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002606 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002607 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002608 goto unlock;
2609 }
2610
2611 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002612 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002613 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002614 goto unlock;
2615 }
2616
2617 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002618
Johan Hedbergb5235a62012-02-21 14:32:24 +02002619unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002620 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002621 return err;
2622}
2623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002624static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002625 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002626{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002627 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002628 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2629 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002630 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002631 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002632 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002634 BT_DBG("request for %s", hdev->name);
2635
2636 if (!lmp_bredr_capable(hdev))
2637 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2638 MGMT_STATUS_NOT_SUPPORTED);
2639
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002640 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002641 if (key_count > max_key_count) {
2642 BT_ERR("load_link_keys: too big key_count value %u",
2643 key_count);
2644 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2645 MGMT_STATUS_INVALID_PARAMS);
2646 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002647
Johan Hedberg86742e12011-11-07 23:13:38 +02002648 expected_len = sizeof(*cp) + key_count *
2649 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002650 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002651 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002652 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002653 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002654 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002655 }
2656
Johan Hedberg4ae143012013-01-20 14:27:13 +02002657 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2658 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2659 MGMT_STATUS_INVALID_PARAMS);
2660
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002661 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002662 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002663
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002664 for (i = 0; i < key_count; i++) {
2665 struct mgmt_link_key_info *key = &cp->keys[i];
2666
Marcel Holtmann8e991132014-01-10 02:07:25 -08002667 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002668 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2669 MGMT_STATUS_INVALID_PARAMS);
2670 }
2671
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002672 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002673
2674 hci_link_keys_clear(hdev);
2675
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002676 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002677 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2678 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002680 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2681 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002682
2683 if (changed)
2684 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002686 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002687 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002688
Johan Hedberg58e92932014-06-24 14:00:26 +03002689 /* Always ignore debug keys and require a new pairing if
2690 * the user wants to use them.
2691 */
2692 if (key->type == HCI_LK_DEBUG_COMBINATION)
2693 continue;
2694
Johan Hedberg7652ff62014-06-24 13:15:49 +03002695 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2696 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002697 }
2698
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002699 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002700
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002701 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002702
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002703 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704}
2705
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002706static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002707 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002708{
2709 struct mgmt_ev_device_unpaired ev;
2710
2711 bacpy(&ev.addr.bdaddr, bdaddr);
2712 ev.addr.type = addr_type;
2713
2714 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002715 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002716}
2717
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002718static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002719 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002720{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002721 struct mgmt_cp_unpair_device *cp = data;
2722 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002723 struct hci_cp_disconnect dc;
2724 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002725 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726 int err;
2727
Johan Hedberga8a1d192011-11-10 15:54:38 +02002728 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002729 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2730 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002731
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002732 if (!bdaddr_type_is_valid(cp->addr.type))
2733 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2734 MGMT_STATUS_INVALID_PARAMS,
2735 &rp, sizeof(rp));
2736
Johan Hedberg118da702013-01-20 14:27:20 +02002737 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2738 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2739 MGMT_STATUS_INVALID_PARAMS,
2740 &rp, sizeof(rp));
2741
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002742 hci_dev_lock(hdev);
2743
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002744 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002745 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002746 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002747 goto unlock;
2748 }
2749
Johan Hedberge0b2b272014-02-18 17:14:31 +02002750 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002751 /* If disconnection is requested, then look up the
2752 * connection. If the remote device is connected, it
2753 * will be later used to terminate the link.
2754 *
2755 * Setting it to NULL explicitly will cause no
2756 * termination of the link.
2757 */
2758 if (cp->disconnect)
2759 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2760 &cp->addr.bdaddr);
2761 else
2762 conn = NULL;
2763
Johan Hedberg124f6e32012-02-09 13:50:12 +02002764 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002765 } else {
2766 u8 addr_type;
2767
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002768 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2769 &cp->addr.bdaddr);
2770 if (conn) {
2771 /* Defer clearing up the connection parameters
2772 * until closing to give a chance of keeping
2773 * them if a repairing happens.
2774 */
2775 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2776
2777 /* If disconnection is not requested, then
2778 * clear the connection variable so that the
2779 * link is not terminated.
2780 */
2781 if (!cp->disconnect)
2782 conn = NULL;
2783 }
2784
Johan Hedberge0b2b272014-02-18 17:14:31 +02002785 if (cp->addr.type == BDADDR_LE_PUBLIC)
2786 addr_type = ADDR_LE_DEV_PUBLIC;
2787 else
2788 addr_type = ADDR_LE_DEV_RANDOM;
2789
Johan Hedberga7ec7332014-02-18 17:14:35 +02002790 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2791
Johan Hedberge0b2b272014-02-18 17:14:31 +02002792 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2793 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002794
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002795 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002796 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002797 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002798 goto unlock;
2799 }
2800
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002801 /* If the connection variable is set, then termination of the
2802 * link is requested.
2803 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002804 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002805 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002806 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002807 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002808 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002809 }
2810
Johan Hedberg124f6e32012-02-09 13:50:12 +02002811 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002813 if (!cmd) {
2814 err = -ENOMEM;
2815 goto unlock;
2816 }
2817
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002818 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 dc.reason = 0x13; /* Remote User Terminated Connection */
2820 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2821 if (err < 0)
2822 mgmt_pending_remove(cmd);
2823
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002824unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002825 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002826 return err;
2827}
2828
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002829static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002830 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002831{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002832 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002833 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002834 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002835 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002836 int err;
2837
2838 BT_DBG("");
2839
Johan Hedberg06a63b12013-01-20 14:27:21 +02002840 memset(&rp, 0, sizeof(rp));
2841 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2842 rp.addr.type = cp->addr.type;
2843
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002844 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002845 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2846 MGMT_STATUS_INVALID_PARAMS,
2847 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002848
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002849 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002850
2851 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002852 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2853 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002854 goto failed;
2855 }
2856
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002857 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002858 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2859 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002860 goto failed;
2861 }
2862
Andre Guedes591f47f2012-04-24 21:02:49 -03002863 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002864 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2865 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002866 else
2867 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002868
Vishal Agarwalf9607272012-06-13 05:32:43 +05302869 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002870 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2871 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002872 goto failed;
2873 }
2874
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002875 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002876 if (!cmd) {
2877 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002878 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002879 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880
Johan Hedbergf5818c22014-12-05 13:36:02 +02002881 cmd->cmd_complete = generic_cmd_complete;
2882
Johan Hedberge3f2f922014-08-18 20:33:33 +03002883 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002884 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002885 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886
2887failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002888 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002889 return err;
2890}
2891
Andre Guedes57c14772012-04-24 21:02:50 -03002892static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002893{
2894 switch (link_type) {
2895 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002896 switch (addr_type) {
2897 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002898 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002899
Johan Hedberg48264f02011-11-09 13:58:58 +02002900 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002901 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002902 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002903 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002904
Johan Hedberg4c659c32011-11-07 23:13:39 +02002905 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002906 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002907 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002908 }
2909}
2910
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002911static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2912 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002913{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002914 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002915 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002916 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002917 int err;
2918 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002919
2920 BT_DBG("");
2921
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002922 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002923
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002924 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002925 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002926 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002927 goto unlock;
2928 }
2929
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002930 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002931 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2932 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002933 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002934 }
2935
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002936 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002937 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002938 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002939 err = -ENOMEM;
2940 goto unlock;
2941 }
2942
Johan Hedberg2784eb42011-01-21 13:56:35 +02002943 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002944 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002945 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2946 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002947 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002948 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002949 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002950 continue;
2951 i++;
2952 }
2953
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002954 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002955
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 /* Recalculate length in case of filtered SCO connections, etc */
2957 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002958
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002959 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002960 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002961
Johan Hedberga38528f2011-01-22 06:46:43 +02002962 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002963
2964unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002965 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966 return err;
2967}
2968
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002969static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002970 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002971{
2972 struct pending_cmd *cmd;
2973 int err;
2974
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002975 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002977 if (!cmd)
2978 return -ENOMEM;
2979
Johan Hedbergd8457692012-02-17 14:24:57 +02002980 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002981 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002982 if (err < 0)
2983 mgmt_pending_remove(cmd);
2984
2985 return err;
2986}
2987
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002988static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002990{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002991 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002992 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002993 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03002994 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002995 int err;
2996
2997 BT_DBG("");
2998
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002999 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003000
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003001 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003002 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003003 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003004 goto failed;
3005 }
3006
Johan Hedbergd8457692012-02-17 14:24:57 +02003007 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003008 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003009 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003010 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003011 goto failed;
3012 }
3013
3014 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003015 struct mgmt_cp_pin_code_neg_reply ncp;
3016
3017 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003018
3019 BT_ERR("PIN code is not 16 bytes long");
3020
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003021 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003022 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003023 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003024 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003025
3026 goto failed;
3027 }
3028
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003029 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003030 if (!cmd) {
3031 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003032 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003033 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003034
Johan Hedbergd8457692012-02-17 14:24:57 +02003035 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003036 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003037 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003038
3039 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3040 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003041 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042
3043failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003044 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003045 return err;
3046}
3047
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003048static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3049 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003050{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003051 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003052
3053 BT_DBG("");
3054
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003055 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3056 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3057 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3058
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003059 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060
3061 hdev->io_capability = cp->io_capability;
3062
3063 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003064 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003065
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003066 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003067
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003068 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3069 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003070}
3071
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003072static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003073{
3074 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003075 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003076
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003077 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003078 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3079 continue;
3080
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081 if (cmd->user_data != conn)
3082 continue;
3083
3084 return cmd;
3085 }
3086
3087 return NULL;
3088}
3089
3090static void pairing_complete(struct pending_cmd *cmd, u8 status)
3091{
3092 struct mgmt_rp_pair_device rp;
3093 struct hci_conn *conn = cmd->user_data;
3094
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003095 bacpy(&rp.addr.bdaddr, &conn->dst);
3096 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003097
Johan Hedbergaee9b212012-02-18 15:07:59 +02003098 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003099 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003100
3101 /* So we don't get further callbacks for this connection */
3102 conn->connect_cfm_cb = NULL;
3103 conn->security_cfm_cb = NULL;
3104 conn->disconn_cfm_cb = NULL;
3105
David Herrmann76a68ba2013-04-06 20:28:37 +02003106 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003107 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003108
Johan Hedberga664b5b2011-02-19 12:06:02 -03003109 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003110
3111 /* The device is paired so there is no need to remove
3112 * its connection parameters anymore.
3113 */
3114 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003115}
3116
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003117void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3118{
3119 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3120 struct pending_cmd *cmd;
3121
3122 cmd = find_pairing(conn);
3123 if (cmd)
3124 pairing_complete(cmd, status);
3125}
3126
Johan Hedberge9a416b2011-02-19 12:05:56 -03003127static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3128{
3129 struct pending_cmd *cmd;
3130
3131 BT_DBG("status %u", status);
3132
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003133 cmd = find_pairing(conn);
3134 if (!cmd)
3135 BT_DBG("Unable to find a pending command");
3136 else
Johan Hedberge2113262012-02-18 15:20:03 +02003137 pairing_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138}
3139
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003140static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303141{
3142 struct pending_cmd *cmd;
3143
3144 BT_DBG("status %u", status);
3145
3146 if (!status)
3147 return;
3148
3149 cmd = find_pairing(conn);
3150 if (!cmd)
3151 BT_DBG("Unable to find a pending command");
3152 else
3153 pairing_complete(cmd, mgmt_status(status));
3154}
3155
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003156static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003157 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003158{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003159 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003160 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003161 struct pending_cmd *cmd;
3162 u8 sec_level, auth_type;
3163 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003164 int err;
3165
3166 BT_DBG("");
3167
Szymon Jancf950a30e2013-01-18 12:48:07 +01003168 memset(&rp, 0, sizeof(rp));
3169 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3170 rp.addr.type = cp->addr.type;
3171
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003172 if (!bdaddr_type_is_valid(cp->addr.type))
3173 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3174 MGMT_STATUS_INVALID_PARAMS,
3175 &rp, sizeof(rp));
3176
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003177 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3178 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3179 MGMT_STATUS_INVALID_PARAMS,
3180 &rp, sizeof(rp));
3181
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003182 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003183
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003184 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003185 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3186 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003187 goto unlock;
3188 }
3189
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003190 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003191 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003192
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003193 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003194 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3195 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003196 } else {
3197 u8 addr_type;
3198
3199 /* Convert from L2CAP channel address type to HCI address type
3200 */
3201 if (cp->addr.type == BDADDR_LE_PUBLIC)
3202 addr_type = ADDR_LE_DEV_PUBLIC;
3203 else
3204 addr_type = ADDR_LE_DEV_RANDOM;
3205
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003206 /* When pairing a new device, it is expected to remember
3207 * this device for future connections. Adding the connection
3208 * parameter information ahead of time allows tracking
3209 * of the slave preferred values and will speed up any
3210 * further connection establishment.
3211 *
3212 * If connection parameters already exist, then they
3213 * will be kept and this function does nothing.
3214 */
3215 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3216
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003217 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003218 sec_level, HCI_LE_CONN_TIMEOUT,
3219 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003220 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003221
Ville Tervo30e76272011-02-22 16:10:53 -03003222 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003223 int status;
3224
3225 if (PTR_ERR(conn) == -EBUSY)
3226 status = MGMT_STATUS_BUSY;
3227 else
3228 status = MGMT_STATUS_CONNECT_FAILED;
3229
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003230 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003231 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003232 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003233 goto unlock;
3234 }
3235
3236 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003237 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003238 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003239 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003240 goto unlock;
3241 }
3242
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003243 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003244 if (!cmd) {
3245 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003246 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003247 goto unlock;
3248 }
3249
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003250 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003251 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003252 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003253 conn->security_cfm_cb = pairing_complete_cb;
3254 conn->disconn_cfm_cb = pairing_complete_cb;
3255 } else {
3256 conn->connect_cfm_cb = le_pairing_complete_cb;
3257 conn->security_cfm_cb = le_pairing_complete_cb;
3258 conn->disconn_cfm_cb = le_pairing_complete_cb;
3259 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003260
Johan Hedberge9a416b2011-02-19 12:05:56 -03003261 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003262 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003263
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003264 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003265 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003266 pairing_complete(cmd, 0);
3267
3268 err = 0;
3269
3270unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003271 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003272 return err;
3273}
3274
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003275static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3276 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003277{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003278 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003279 struct pending_cmd *cmd;
3280 struct hci_conn *conn;
3281 int err;
3282
3283 BT_DBG("");
3284
Johan Hedberg28424702012-02-02 04:02:29 +02003285 hci_dev_lock(hdev);
3286
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003287 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003288 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003289 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003290 goto unlock;
3291 }
3292
Johan Hedberg28424702012-02-02 04:02:29 +02003293 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3294 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003295 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003296 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003297 goto unlock;
3298 }
3299
3300 conn = cmd->user_data;
3301
3302 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003303 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003304 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003305 goto unlock;
3306 }
3307
3308 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3309
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003310 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003311 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003312unlock:
3313 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003314 return err;
3315}
3316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003317static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003318 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003319 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003320{
Johan Hedberga5c29682011-02-19 12:05:57 -03003321 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003322 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003323 int err;
3324
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003325 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003326
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003327 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003328 err = cmd_complete(sk, hdev->id, mgmt_op,
3329 MGMT_STATUS_NOT_POWERED, addr,
3330 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003331 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003332 }
3333
Johan Hedberg1707c602013-03-15 17:07:15 -05003334 if (addr->type == BDADDR_BREDR)
3335 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003336 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003337 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003338
Johan Hedberg272d90d2012-02-09 15:26:12 +02003339 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003340 err = cmd_complete(sk, hdev->id, mgmt_op,
3341 MGMT_STATUS_NOT_CONNECTED, addr,
3342 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003343 goto done;
3344 }
3345
Johan Hedberg1707c602013-03-15 17:07:15 -05003346 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003347 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003348 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003349 err = cmd_complete(sk, hdev->id, mgmt_op,
3350 MGMT_STATUS_SUCCESS, addr,
3351 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003352 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003353 err = cmd_complete(sk, hdev->id, mgmt_op,
3354 MGMT_STATUS_FAILED, addr,
3355 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003356
Brian Gix47c15e22011-11-16 13:53:14 -08003357 goto done;
3358 }
3359
Johan Hedberg1707c602013-03-15 17:07:15 -05003360 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003361 if (!cmd) {
3362 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003363 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003364 }
3365
Brian Gix0df4c182011-11-16 13:53:13 -08003366 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003367 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3368 struct hci_cp_user_passkey_reply cp;
3369
Johan Hedberg1707c602013-03-15 17:07:15 -05003370 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003371 cp.passkey = passkey;
3372 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3373 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003374 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3375 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003376
Johan Hedberga664b5b2011-02-19 12:06:02 -03003377 if (err < 0)
3378 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003379
Brian Gix0df4c182011-11-16 13:53:13 -08003380done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003381 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003382 return err;
3383}
3384
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303385static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3386 void *data, u16 len)
3387{
3388 struct mgmt_cp_pin_code_neg_reply *cp = data;
3389
3390 BT_DBG("");
3391
Johan Hedberg1707c602013-03-15 17:07:15 -05003392 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303393 MGMT_OP_PIN_CODE_NEG_REPLY,
3394 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3395}
3396
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003397static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3398 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003399{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003400 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003401
3402 BT_DBG("");
3403
3404 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003405 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003406 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003407
Johan Hedberg1707c602013-03-15 17:07:15 -05003408 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409 MGMT_OP_USER_CONFIRM_REPLY,
3410 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003411}
3412
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003413static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003414 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003415{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003416 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003417
3418 BT_DBG("");
3419
Johan Hedberg1707c602013-03-15 17:07:15 -05003420 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3422 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003423}
3424
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003425static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3426 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003427{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003428 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003429
3430 BT_DBG("");
3431
Johan Hedberg1707c602013-03-15 17:07:15 -05003432 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003433 MGMT_OP_USER_PASSKEY_REPLY,
3434 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003435}
3436
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003437static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003438 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003439{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003440 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003441
3442 BT_DBG("");
3443
Johan Hedberg1707c602013-03-15 17:07:15 -05003444 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003445 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3446 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003447}
3448
Johan Hedberg13928972013-03-15 17:07:00 -05003449static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003450{
Johan Hedberg13928972013-03-15 17:07:00 -05003451 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003452 struct hci_cp_write_local_name cp;
3453
Johan Hedberg13928972013-03-15 17:07:00 -05003454 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003455
Johan Hedberg890ea892013-03-15 17:06:52 -05003456 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003457}
3458
Johan Hedberg13928972013-03-15 17:07:00 -05003459static void set_name_complete(struct hci_dev *hdev, u8 status)
3460{
3461 struct mgmt_cp_set_local_name *cp;
3462 struct pending_cmd *cmd;
3463
3464 BT_DBG("status 0x%02x", status);
3465
3466 hci_dev_lock(hdev);
3467
3468 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3469 if (!cmd)
3470 goto unlock;
3471
3472 cp = cmd->param;
3473
3474 if (status)
3475 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3476 mgmt_status(status));
3477 else
3478 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3479 cp, sizeof(*cp));
3480
3481 mgmt_pending_remove(cmd);
3482
3483unlock:
3484 hci_dev_unlock(hdev);
3485}
3486
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003487static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003488 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003489{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003490 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003491 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003492 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003493 int err;
3494
3495 BT_DBG("");
3496
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003497 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003498
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003499 /* If the old values are the same as the new ones just return a
3500 * direct command complete event.
3501 */
3502 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3503 !memcmp(hdev->short_name, cp->short_name,
3504 sizeof(hdev->short_name))) {
3505 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3506 data, len);
3507 goto failed;
3508 }
3509
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003510 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003511
Johan Hedbergb5235a62012-02-21 14:32:24 +02003512 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003513 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003514
3515 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003516 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003517 if (err < 0)
3518 goto failed;
3519
3520 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003521 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003522
Johan Hedbergb5235a62012-02-21 14:32:24 +02003523 goto failed;
3524 }
3525
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003526 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003527 if (!cmd) {
3528 err = -ENOMEM;
3529 goto failed;
3530 }
3531
Johan Hedberg13928972013-03-15 17:07:00 -05003532 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3533
Johan Hedberg890ea892013-03-15 17:06:52 -05003534 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003535
3536 if (lmp_bredr_capable(hdev)) {
3537 update_name(&req);
3538 update_eir(&req);
3539 }
3540
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003541 /* The name is stored in the scan response data and so
3542 * no need to udpate the advertising data here.
3543 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003544 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003545 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003546
Johan Hedberg13928972013-03-15 17:07:00 -05003547 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003548 if (err < 0)
3549 mgmt_pending_remove(cmd);
3550
3551failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003552 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003553 return err;
3554}
3555
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003556static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003557 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003558{
Szymon Jancc35938b2011-03-22 13:12:21 +01003559 struct pending_cmd *cmd;
3560 int err;
3561
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003562 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003563
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003564 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003565
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003566 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003567 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003568 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003569 goto unlock;
3570 }
3571
Andre Guedes9a1a1992012-07-24 15:03:48 -03003572 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003573 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003574 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003575 goto unlock;
3576 }
3577
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003578 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003579 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003580 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003581 goto unlock;
3582 }
3583
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003584 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003585 if (!cmd) {
3586 err = -ENOMEM;
3587 goto unlock;
3588 }
3589
Johan Hedberg710f11c2014-05-26 11:21:22 +03003590 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003591 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3592 0, NULL);
3593 else
3594 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3595
Szymon Jancc35938b2011-03-22 13:12:21 +01003596 if (err < 0)
3597 mgmt_pending_remove(cmd);
3598
3599unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003600 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003601 return err;
3602}
3603
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003604static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003605 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003606{
Szymon Janc2763eda2011-03-22 13:12:22 +01003607 int err;
3608
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003609 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003611 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003612
Marcel Holtmannec109112014-01-10 02:07:30 -08003613 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3614 struct mgmt_cp_add_remote_oob_data *cp = data;
3615 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003616
Johan Hedbergc19a4952014-11-17 20:52:19 +02003617 if (cp->addr.type != BDADDR_BREDR) {
3618 err = cmd_complete(sk, hdev->id,
3619 MGMT_OP_ADD_REMOTE_OOB_DATA,
3620 MGMT_STATUS_INVALID_PARAMS,
3621 &cp->addr, sizeof(cp->addr));
3622 goto unlock;
3623 }
3624
Marcel Holtmannec109112014-01-10 02:07:30 -08003625 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003626 cp->addr.type, cp->hash,
3627 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003628 if (err < 0)
3629 status = MGMT_STATUS_FAILED;
3630 else
3631 status = MGMT_STATUS_SUCCESS;
3632
3633 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3634 status, &cp->addr, sizeof(cp->addr));
3635 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3636 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003637 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003638 u8 status;
3639
Johan Hedbergc19a4952014-11-17 20:52:19 +02003640 if (cp->addr.type != BDADDR_BREDR) {
3641 err = cmd_complete(sk, hdev->id,
3642 MGMT_OP_ADD_REMOTE_OOB_DATA,
3643 MGMT_STATUS_INVALID_PARAMS,
3644 &cp->addr, sizeof(cp->addr));
3645 goto unlock;
3646 }
3647
Johan Hedberg86df9202014-10-26 20:52:27 +01003648 if (bdaddr_type_is_le(cp->addr.type)) {
3649 rand192 = NULL;
3650 hash192 = NULL;
3651 } else {
3652 rand192 = cp->rand192;
3653 hash192 = cp->hash192;
3654 }
3655
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003656 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003657 cp->addr.type, hash192, rand192,
3658 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003659 if (err < 0)
3660 status = MGMT_STATUS_FAILED;
3661 else
3662 status = MGMT_STATUS_SUCCESS;
3663
3664 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3665 status, &cp->addr, sizeof(cp->addr));
3666 } else {
3667 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3668 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3669 MGMT_STATUS_INVALID_PARAMS);
3670 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003671
Johan Hedbergc19a4952014-11-17 20:52:19 +02003672unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003673 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003674 return err;
3675}
3676
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003677static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003678 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003679{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003680 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003681 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003682 int err;
3683
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003684 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003685
Johan Hedbergc19a4952014-11-17 20:52:19 +02003686 if (cp->addr.type != BDADDR_BREDR)
3687 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3688 MGMT_STATUS_INVALID_PARAMS,
3689 &cp->addr, sizeof(cp->addr));
3690
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003691 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003692
Johan Hedbergeedbd582014-11-15 09:34:23 +02003693 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3694 hci_remote_oob_data_clear(hdev);
3695 status = MGMT_STATUS_SUCCESS;
3696 goto done;
3697 }
3698
Johan Hedberg6928a922014-10-26 20:46:09 +01003699 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003700 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003701 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003702 else
Szymon Janca6785be2012-12-13 15:11:21 +01003703 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003704
Johan Hedbergeedbd582014-11-15 09:34:23 +02003705done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003706 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003707 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003708
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003709 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003710 return err;
3711}
3712
Marcel Holtmann80190442014-12-04 11:36:36 +01003713static bool trigger_discovery(struct hci_request *req, u8 *status)
3714{
3715 struct hci_dev *hdev = req->hdev;
3716 struct hci_cp_le_set_scan_param param_cp;
3717 struct hci_cp_le_set_scan_enable enable_cp;
3718 struct hci_cp_inquiry inq_cp;
3719 /* General inquiry access code (GIAC) */
3720 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3721 u8 own_addr_type;
3722 int err;
3723
3724 switch (hdev->discovery.type) {
3725 case DISCOV_TYPE_BREDR:
3726 *status = mgmt_bredr_support(hdev);
3727 if (*status)
3728 return false;
3729
3730 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3731 *status = MGMT_STATUS_BUSY;
3732 return false;
3733 }
3734
3735 hci_inquiry_cache_flush(hdev);
3736
3737 memset(&inq_cp, 0, sizeof(inq_cp));
3738 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3739 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3740 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3741 break;
3742
3743 case DISCOV_TYPE_LE:
3744 case DISCOV_TYPE_INTERLEAVED:
3745 *status = mgmt_le_support(hdev);
3746 if (*status)
3747 return false;
3748
3749 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3750 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3751 *status = MGMT_STATUS_NOT_SUPPORTED;
3752 return false;
3753 }
3754
3755 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3756 /* Don't let discovery abort an outgoing
3757 * connection attempt that's using directed
3758 * advertising.
3759 */
3760 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3761 BT_CONNECT)) {
3762 *status = MGMT_STATUS_REJECTED;
3763 return false;
3764 }
3765
3766 disable_advertising(req);
3767 }
3768
3769 /* If controller is scanning, it means the background scanning
3770 * is running. Thus, we should temporarily stop it in order to
3771 * set the discovery scanning parameters.
3772 */
3773 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3774 hci_req_add_le_scan_disable(req);
3775
3776 memset(&param_cp, 0, sizeof(param_cp));
3777
3778 /* All active scans will be done with either a resolvable
3779 * private address (when privacy feature has been enabled)
3780 * or unresolvable private address.
3781 */
3782 err = hci_update_random_address(req, true, &own_addr_type);
3783 if (err < 0) {
3784 *status = MGMT_STATUS_FAILED;
3785 return false;
3786 }
3787
3788 param_cp.type = LE_SCAN_ACTIVE;
3789 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3790 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3791 param_cp.own_address_type = own_addr_type;
3792 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3793 &param_cp);
3794
3795 memset(&enable_cp, 0, sizeof(enable_cp));
3796 enable_cp.enable = LE_SCAN_ENABLE;
3797 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3798 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3799 &enable_cp);
3800 break;
3801
3802 default:
3803 *status = MGMT_STATUS_INVALID_PARAMS;
3804 return false;
3805 }
3806
3807 return true;
3808}
3809
Andre Guedes7c307722013-04-30 15:29:28 -03003810static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3811{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003812 struct pending_cmd *cmd;
3813 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003814
Andre Guedes7c307722013-04-30 15:29:28 -03003815 BT_DBG("status %d", status);
3816
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003817 hci_dev_lock(hdev);
3818
3819 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003820 if (!cmd)
3821 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3822
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003823 if (cmd) {
3824 u8 type = hdev->discovery.type;
3825
3826 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
3827 mgmt_status(status), &type, sizeof(type));
3828 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003829 }
3830
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003831 if (status) {
3832 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3833 goto unlock;
3834 }
3835
Andre Guedes7c307722013-04-30 15:29:28 -03003836 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003837
3838 switch (hdev->discovery.type) {
3839 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003840 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003841 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003842 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003843 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003844 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003845 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003846 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003847 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003848 default:
3849 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003850 timeout = 0;
3851 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003852 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003853
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003854 if (timeout)
3855 queue_delayed_work(hdev->workqueue,
3856 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003857
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003858unlock:
3859 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003860}
3861
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003862static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003863 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003864{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003865 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003866 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003867 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003868 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003869 int err;
3870
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003871 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003872
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003873 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003874
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003875 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003876 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3877 MGMT_STATUS_NOT_POWERED,
3878 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003879 goto failed;
3880 }
3881
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003882 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3883 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003884 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3885 MGMT_STATUS_BUSY, &cp->type,
3886 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003887 goto failed;
3888 }
3889
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003890 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003891 if (!cmd) {
3892 err = -ENOMEM;
3893 goto failed;
3894 }
3895
Marcel Holtmann22078802014-12-05 11:45:22 +01003896 /* Clear the discovery filter first to free any previously
3897 * allocated memory for the UUID list.
3898 */
3899 hci_discovery_filter_clear(hdev);
3900
Andre Guedes4aab14e2012-02-17 20:39:36 -03003901 hdev->discovery.type = cp->type;
3902
Andre Guedes7c307722013-04-30 15:29:28 -03003903 hci_req_init(&req, hdev);
3904
Marcel Holtmann80190442014-12-04 11:36:36 +01003905 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003906 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003907 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003908 mgmt_pending_remove(cmd);
3909 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003910 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003911
Andre Guedes7c307722013-04-30 15:29:28 -03003912 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003913 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003914 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003915 goto failed;
3916 }
3917
3918 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003919
3920failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003921 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003922 return err;
3923}
3924
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003925static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3926 void *data, u16 len)
3927{
3928 struct mgmt_cp_start_service_discovery *cp = data;
3929 struct pending_cmd *cmd;
3930 struct hci_request req;
3931 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3932 u16 uuid_count, expected_len;
3933 u8 status;
3934 int err;
3935
3936 BT_DBG("%s", hdev->name);
3937
3938 hci_dev_lock(hdev);
3939
3940 if (!hdev_is_powered(hdev)) {
3941 err = cmd_complete(sk, hdev->id,
3942 MGMT_OP_START_SERVICE_DISCOVERY,
3943 MGMT_STATUS_NOT_POWERED,
3944 &cp->type, sizeof(cp->type));
3945 goto failed;
3946 }
3947
3948 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3949 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3950 err = cmd_complete(sk, hdev->id,
3951 MGMT_OP_START_SERVICE_DISCOVERY,
3952 MGMT_STATUS_BUSY, &cp->type,
3953 sizeof(cp->type));
3954 goto failed;
3955 }
3956
3957 uuid_count = __le16_to_cpu(cp->uuid_count);
3958 if (uuid_count > max_uuid_count) {
3959 BT_ERR("service_discovery: too big uuid_count value %u",
3960 uuid_count);
3961 err = cmd_complete(sk, hdev->id,
3962 MGMT_OP_START_SERVICE_DISCOVERY,
3963 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3964 sizeof(cp->type));
3965 goto failed;
3966 }
3967
3968 expected_len = sizeof(*cp) + uuid_count * 16;
3969 if (expected_len != len) {
3970 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3971 expected_len, len);
3972 err = cmd_complete(sk, hdev->id,
3973 MGMT_OP_START_SERVICE_DISCOVERY,
3974 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3975 sizeof(cp->type));
3976 goto failed;
3977 }
3978
3979 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
3980 hdev, NULL, 0);
3981 if (!cmd) {
3982 err = -ENOMEM;
3983 goto failed;
3984 }
3985
Marcel Holtmann22078802014-12-05 11:45:22 +01003986 /* Clear the discovery filter first to free any previously
3987 * allocated memory for the UUID list.
3988 */
3989 hci_discovery_filter_clear(hdev);
3990
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003991 hdev->discovery.type = cp->type;
3992 hdev->discovery.rssi = cp->rssi;
3993 hdev->discovery.uuid_count = uuid_count;
3994
3995 if (uuid_count > 0) {
3996 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
3997 GFP_KERNEL);
3998 if (!hdev->discovery.uuids) {
3999 err = cmd_complete(sk, hdev->id,
4000 MGMT_OP_START_SERVICE_DISCOVERY,
4001 MGMT_STATUS_FAILED,
4002 &cp->type, sizeof(cp->type));
4003 mgmt_pending_remove(cmd);
4004 goto failed;
4005 }
4006 }
4007
4008 hci_req_init(&req, hdev);
4009
4010 if (!trigger_discovery(&req, &status)) {
4011 err = cmd_complete(sk, hdev->id,
4012 MGMT_OP_START_SERVICE_DISCOVERY,
4013 status, &cp->type, sizeof(cp->type));
4014 mgmt_pending_remove(cmd);
4015 goto failed;
4016 }
4017
4018 err = hci_req_run(&req, start_discovery_complete);
4019 if (err < 0) {
4020 mgmt_pending_remove(cmd);
4021 goto failed;
4022 }
4023
4024 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4025
4026failed:
4027 hci_dev_unlock(hdev);
4028 return err;
4029}
4030
Andre Guedes0e05bba2013-04-30 15:29:33 -03004031static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4032{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004033 struct pending_cmd *cmd;
4034
Andre Guedes0e05bba2013-04-30 15:29:33 -03004035 BT_DBG("status %d", status);
4036
4037 hci_dev_lock(hdev);
4038
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004039 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4040 if (cmd) {
4041 u8 type = hdev->discovery.type;
4042
4043 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
4044 mgmt_status(status), &type, sizeof(type));
4045 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004046 }
4047
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004048 if (!status)
4049 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004050
Andre Guedes0e05bba2013-04-30 15:29:33 -03004051 hci_dev_unlock(hdev);
4052}
4053
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004054static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004055 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004056{
Johan Hedbergd9306502012-02-20 23:25:18 +02004057 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004058 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004059 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004060 int err;
4061
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004062 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004063
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004064 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004065
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004066 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004067 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004068 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4069 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004070 goto unlock;
4071 }
4072
4073 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004074 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004075 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4076 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004077 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004078 }
4079
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004080 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04004081 if (!cmd) {
4082 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004083 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004084 }
4085
Andre Guedes0e05bba2013-04-30 15:29:33 -03004086 hci_req_init(&req, hdev);
4087
Johan Hedberg21a60d32014-06-10 14:05:58 +03004088 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004089
Johan Hedberg21a60d32014-06-10 14:05:58 +03004090 err = hci_req_run(&req, stop_discovery_complete);
4091 if (!err) {
4092 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004093 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004094 }
4095
Johan Hedberg21a60d32014-06-10 14:05:58 +03004096 mgmt_pending_remove(cmd);
4097
4098 /* If no HCI commands were sent we're done */
4099 if (err == -ENODATA) {
4100 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4101 &mgmt_cp->type, sizeof(mgmt_cp->type));
4102 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4103 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004104
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004105unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004106 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004107 return err;
4108}
4109
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004110static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004111 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004112{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004113 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004114 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004115 int err;
4116
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004117 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004118
Johan Hedberg561aafb2012-01-04 13:31:59 +02004119 hci_dev_lock(hdev);
4120
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004121 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004122 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4123 MGMT_STATUS_FAILED, &cp->addr,
4124 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004125 goto failed;
4126 }
4127
Johan Hedberga198e7b2012-02-17 14:27:06 +02004128 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004129 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004130 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4131 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4132 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004133 goto failed;
4134 }
4135
4136 if (cp->name_known) {
4137 e->name_state = NAME_KNOWN;
4138 list_del(&e->list);
4139 } else {
4140 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004141 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004142 }
4143
Johan Hedberge3846622013-01-09 15:29:33 +02004144 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4145 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004146
4147failed:
4148 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004149 return err;
4150}
4151
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004152static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004153 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004154{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004155 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004156 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004157 int err;
4158
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004159 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004160
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004161 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004162 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4163 MGMT_STATUS_INVALID_PARAMS,
4164 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004166 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004167
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004168 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4169 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004170 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004171 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004172 goto done;
4173 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004174
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004175 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4176 sk);
4177 status = MGMT_STATUS_SUCCESS;
4178
4179done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004180 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004181 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004183 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004184
4185 return err;
4186}
4187
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004188static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004189 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004190{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004191 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004192 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004193 int err;
4194
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004195 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004196
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004197 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004198 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4199 MGMT_STATUS_INVALID_PARAMS,
4200 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004202 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004203
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004204 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4205 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004206 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004207 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004208 goto done;
4209 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004210
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004211 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4212 sk);
4213 status = MGMT_STATUS_SUCCESS;
4214
4215done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004216 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004217 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004218
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004219 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004220
4221 return err;
4222}
4223
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004224static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4225 u16 len)
4226{
4227 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004228 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004229 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004230 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004231
4232 BT_DBG("%s", hdev->name);
4233
Szymon Jancc72d4b82012-03-16 16:02:57 +01004234 source = __le16_to_cpu(cp->source);
4235
4236 if (source > 0x0002)
4237 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4238 MGMT_STATUS_INVALID_PARAMS);
4239
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004240 hci_dev_lock(hdev);
4241
Szymon Jancc72d4b82012-03-16 16:02:57 +01004242 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004243 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4244 hdev->devid_product = __le16_to_cpu(cp->product);
4245 hdev->devid_version = __le16_to_cpu(cp->version);
4246
4247 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4248
Johan Hedberg890ea892013-03-15 17:06:52 -05004249 hci_req_init(&req, hdev);
4250 update_eir(&req);
4251 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004252
4253 hci_dev_unlock(hdev);
4254
4255 return err;
4256}
4257
Johan Hedberg4375f102013-09-25 13:26:10 +03004258static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4259{
4260 struct cmd_lookup match = { NULL, hdev };
4261
4262 if (status) {
4263 u8 mgmt_err = mgmt_status(status);
4264
4265 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4266 cmd_status_rsp, &mgmt_err);
4267 return;
4268 }
4269
Johan Hedbergc93bd152014-07-08 15:07:48 +03004270 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4271 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4272 else
4273 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4274
Johan Hedberg4375f102013-09-25 13:26:10 +03004275 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4276 &match);
4277
4278 new_settings(hdev, match.sk);
4279
4280 if (match.sk)
4281 sock_put(match.sk);
4282}
4283
Marcel Holtmann21b51872013-10-10 09:47:53 -07004284static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4285 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004286{
4287 struct mgmt_mode *cp = data;
4288 struct pending_cmd *cmd;
4289 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004290 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004291 int err;
4292
4293 BT_DBG("request for %s", hdev->name);
4294
Johan Hedberge6fe7982013-10-02 15:45:22 +03004295 status = mgmt_le_support(hdev);
4296 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004297 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004298 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004299
4300 if (cp->val != 0x00 && cp->val != 0x01)
4301 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4302 MGMT_STATUS_INVALID_PARAMS);
4303
4304 hci_dev_lock(hdev);
4305
4306 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004307 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004308
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004309 /* The following conditions are ones which mean that we should
4310 * not do any HCI communication but directly send a mgmt
4311 * response to user space (after toggling the flag if
4312 * necessary).
4313 */
4314 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004315 hci_conn_num(hdev, LE_LINK) > 0 ||
4316 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4317 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004318 bool changed = false;
4319
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004320 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4321 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004322 changed = true;
4323 }
4324
4325 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4326 if (err < 0)
4327 goto unlock;
4328
4329 if (changed)
4330 err = new_settings(hdev, sk);
4331
4332 goto unlock;
4333 }
4334
4335 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4336 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4337 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4338 MGMT_STATUS_BUSY);
4339 goto unlock;
4340 }
4341
4342 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4343 if (!cmd) {
4344 err = -ENOMEM;
4345 goto unlock;
4346 }
4347
4348 hci_req_init(&req, hdev);
4349
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004350 if (val)
4351 enable_advertising(&req);
4352 else
4353 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004354
4355 err = hci_req_run(&req, set_advertising_complete);
4356 if (err < 0)
4357 mgmt_pending_remove(cmd);
4358
4359unlock:
4360 hci_dev_unlock(hdev);
4361 return err;
4362}
4363
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004364static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4365 void *data, u16 len)
4366{
4367 struct mgmt_cp_set_static_address *cp = data;
4368 int err;
4369
4370 BT_DBG("%s", hdev->name);
4371
Marcel Holtmann62af4442013-10-02 22:10:32 -07004372 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004373 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004374 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004375
4376 if (hdev_is_powered(hdev))
4377 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4378 MGMT_STATUS_REJECTED);
4379
4380 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4381 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4382 return cmd_status(sk, hdev->id,
4383 MGMT_OP_SET_STATIC_ADDRESS,
4384 MGMT_STATUS_INVALID_PARAMS);
4385
4386 /* Two most significant bits shall be set */
4387 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4388 return cmd_status(sk, hdev->id,
4389 MGMT_OP_SET_STATIC_ADDRESS,
4390 MGMT_STATUS_INVALID_PARAMS);
4391 }
4392
4393 hci_dev_lock(hdev);
4394
4395 bacpy(&hdev->static_addr, &cp->bdaddr);
4396
4397 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4398
4399 hci_dev_unlock(hdev);
4400
4401 return err;
4402}
4403
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004404static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4405 void *data, u16 len)
4406{
4407 struct mgmt_cp_set_scan_params *cp = data;
4408 __u16 interval, window;
4409 int err;
4410
4411 BT_DBG("%s", hdev->name);
4412
4413 if (!lmp_le_capable(hdev))
4414 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4415 MGMT_STATUS_NOT_SUPPORTED);
4416
4417 interval = __le16_to_cpu(cp->interval);
4418
4419 if (interval < 0x0004 || interval > 0x4000)
4420 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4421 MGMT_STATUS_INVALID_PARAMS);
4422
4423 window = __le16_to_cpu(cp->window);
4424
4425 if (window < 0x0004 || window > 0x4000)
4426 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4427 MGMT_STATUS_INVALID_PARAMS);
4428
Marcel Holtmann899e1072013-10-14 09:55:32 -07004429 if (window > interval)
4430 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4431 MGMT_STATUS_INVALID_PARAMS);
4432
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004433 hci_dev_lock(hdev);
4434
4435 hdev->le_scan_interval = interval;
4436 hdev->le_scan_window = window;
4437
4438 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4439
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004440 /* If background scan is running, restart it so new parameters are
4441 * loaded.
4442 */
4443 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4444 hdev->discovery.state == DISCOVERY_STOPPED) {
4445 struct hci_request req;
4446
4447 hci_req_init(&req, hdev);
4448
4449 hci_req_add_le_scan_disable(&req);
4450 hci_req_add_le_passive_scan(&req);
4451
4452 hci_req_run(&req, NULL);
4453 }
4454
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004455 hci_dev_unlock(hdev);
4456
4457 return err;
4458}
4459
Johan Hedberg33e38b32013-03-15 17:07:05 -05004460static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4461{
4462 struct pending_cmd *cmd;
4463
4464 BT_DBG("status 0x%02x", status);
4465
4466 hci_dev_lock(hdev);
4467
4468 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4469 if (!cmd)
4470 goto unlock;
4471
4472 if (status) {
4473 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4474 mgmt_status(status));
4475 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004476 struct mgmt_mode *cp = cmd->param;
4477
4478 if (cp->val)
4479 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4480 else
4481 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4482
Johan Hedberg33e38b32013-03-15 17:07:05 -05004483 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4484 new_settings(hdev, cmd->sk);
4485 }
4486
4487 mgmt_pending_remove(cmd);
4488
4489unlock:
4490 hci_dev_unlock(hdev);
4491}
4492
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004493static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004494 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004495{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004496 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004497 struct pending_cmd *cmd;
4498 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004499 int err;
4500
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004501 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004502
Johan Hedberg56f87902013-10-02 13:43:13 +03004503 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4504 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004505 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4506 MGMT_STATUS_NOT_SUPPORTED);
4507
Johan Hedberga7e80f22013-01-09 16:05:19 +02004508 if (cp->val != 0x00 && cp->val != 0x01)
4509 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4510 MGMT_STATUS_INVALID_PARAMS);
4511
Johan Hedberg5400c042012-02-21 16:40:33 +02004512 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004513 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004514 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004515
4516 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004517 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004518 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004519
4520 hci_dev_lock(hdev);
4521
Johan Hedberg05cbf292013-03-15 17:07:07 -05004522 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4523 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4524 MGMT_STATUS_BUSY);
4525 goto unlock;
4526 }
4527
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004528 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4529 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4530 hdev);
4531 goto unlock;
4532 }
4533
Johan Hedberg33e38b32013-03-15 17:07:05 -05004534 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4535 data, len);
4536 if (!cmd) {
4537 err = -ENOMEM;
4538 goto unlock;
4539 }
4540
4541 hci_req_init(&req, hdev);
4542
Johan Hedberg406d7802013-03-15 17:07:09 -05004543 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004544
4545 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004546 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004547 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004548 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004549 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004550 }
4551
Johan Hedberg33e38b32013-03-15 17:07:05 -05004552unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004553 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004554
Antti Julkuf6422ec2011-06-22 13:11:56 +03004555 return err;
4556}
4557
Johan Hedberg0663ca22013-10-02 13:43:14 +03004558static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4559{
4560 struct pending_cmd *cmd;
4561
4562 BT_DBG("status 0x%02x", status);
4563
4564 hci_dev_lock(hdev);
4565
4566 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4567 if (!cmd)
4568 goto unlock;
4569
4570 if (status) {
4571 u8 mgmt_err = mgmt_status(status);
4572
4573 /* We need to restore the flag if related HCI commands
4574 * failed.
4575 */
4576 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4577
4578 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4579 } else {
4580 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4581 new_settings(hdev, cmd->sk);
4582 }
4583
4584 mgmt_pending_remove(cmd);
4585
4586unlock:
4587 hci_dev_unlock(hdev);
4588}
4589
4590static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4591{
4592 struct mgmt_mode *cp = data;
4593 struct pending_cmd *cmd;
4594 struct hci_request req;
4595 int err;
4596
4597 BT_DBG("request for %s", hdev->name);
4598
4599 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4600 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4601 MGMT_STATUS_NOT_SUPPORTED);
4602
4603 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4604 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4605 MGMT_STATUS_REJECTED);
4606
4607 if (cp->val != 0x00 && cp->val != 0x01)
4608 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4609 MGMT_STATUS_INVALID_PARAMS);
4610
4611 hci_dev_lock(hdev);
4612
4613 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4614 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4615 goto unlock;
4616 }
4617
4618 if (!hdev_is_powered(hdev)) {
4619 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004620 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4621 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4622 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4623 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4624 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4625 }
4626
4627 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4628
4629 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4630 if (err < 0)
4631 goto unlock;
4632
4633 err = new_settings(hdev, sk);
4634 goto unlock;
4635 }
4636
4637 /* Reject disabling when powered on */
4638 if (!cp->val) {
4639 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4640 MGMT_STATUS_REJECTED);
4641 goto unlock;
4642 }
4643
4644 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4645 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4646 MGMT_STATUS_BUSY);
4647 goto unlock;
4648 }
4649
4650 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4651 if (!cmd) {
4652 err = -ENOMEM;
4653 goto unlock;
4654 }
4655
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004656 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004657 * generates the correct flags.
4658 */
4659 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4660
4661 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004662
Johan Hedberg432df052014-08-01 11:13:31 +03004663 write_fast_connectable(&req, false);
4664 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004665
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004666 /* Since only the advertising data flags will change, there
4667 * is no need to update the scan response data.
4668 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004669 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004670
Johan Hedberg0663ca22013-10-02 13:43:14 +03004671 err = hci_req_run(&req, set_bredr_complete);
4672 if (err < 0)
4673 mgmt_pending_remove(cmd);
4674
4675unlock:
4676 hci_dev_unlock(hdev);
4677 return err;
4678}
4679
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004680static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4681 void *data, u16 len)
4682{
4683 struct mgmt_mode *cp = data;
4684 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004685 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004686 int err;
4687
4688 BT_DBG("request for %s", hdev->name);
4689
Johan Hedberga3209692014-05-26 11:23:35 +03004690 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4691 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004692 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4693 MGMT_STATUS_NOT_SUPPORTED);
4694
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004695 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004696 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4697 MGMT_STATUS_INVALID_PARAMS);
4698
4699 hci_dev_lock(hdev);
4700
Johan Hedberga3209692014-05-26 11:23:35 +03004701 if (!hdev_is_powered(hdev) ||
4702 (!lmp_sc_capable(hdev) &&
4703 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4704 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004705 bool changed;
4706
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004707 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004708 changed = !test_and_set_bit(HCI_SC_ENABLED,
4709 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004710 if (cp->val == 0x02)
4711 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4712 else
4713 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4714 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004715 changed = test_and_clear_bit(HCI_SC_ENABLED,
4716 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004717 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4718 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004719
4720 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4721 if (err < 0)
4722 goto failed;
4723
4724 if (changed)
4725 err = new_settings(hdev, sk);
4726
4727 goto failed;
4728 }
4729
4730 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4731 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4732 MGMT_STATUS_BUSY);
4733 goto failed;
4734 }
4735
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004736 val = !!cp->val;
4737
4738 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4739 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004740 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4741 goto failed;
4742 }
4743
4744 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4745 if (!cmd) {
4746 err = -ENOMEM;
4747 goto failed;
4748 }
4749
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004750 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004751 if (err < 0) {
4752 mgmt_pending_remove(cmd);
4753 goto failed;
4754 }
4755
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004756 if (cp->val == 0x02)
4757 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4758 else
4759 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4760
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004761failed:
4762 hci_dev_unlock(hdev);
4763 return err;
4764}
4765
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004766static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4767 void *data, u16 len)
4768{
4769 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004770 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004771 int err;
4772
4773 BT_DBG("request for %s", hdev->name);
4774
Johan Hedbergb97109792014-06-24 14:00:28 +03004775 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004776 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4777 MGMT_STATUS_INVALID_PARAMS);
4778
4779 hci_dev_lock(hdev);
4780
4781 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004782 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4783 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004784 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004785 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4786 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004787
Johan Hedbergb97109792014-06-24 14:00:28 +03004788 if (cp->val == 0x02)
4789 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4790 &hdev->dev_flags);
4791 else
4792 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4793 &hdev->dev_flags);
4794
4795 if (hdev_is_powered(hdev) && use_changed &&
4796 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4797 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4798 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4799 sizeof(mode), &mode);
4800 }
4801
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004802 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4803 if (err < 0)
4804 goto unlock;
4805
4806 if (changed)
4807 err = new_settings(hdev, sk);
4808
4809unlock:
4810 hci_dev_unlock(hdev);
4811 return err;
4812}
4813
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004814static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4815 u16 len)
4816{
4817 struct mgmt_cp_set_privacy *cp = cp_data;
4818 bool changed;
4819 int err;
4820
4821 BT_DBG("request for %s", hdev->name);
4822
4823 if (!lmp_le_capable(hdev))
4824 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4825 MGMT_STATUS_NOT_SUPPORTED);
4826
4827 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4828 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4829 MGMT_STATUS_INVALID_PARAMS);
4830
4831 if (hdev_is_powered(hdev))
4832 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4833 MGMT_STATUS_REJECTED);
4834
4835 hci_dev_lock(hdev);
4836
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004837 /* If user space supports this command it is also expected to
4838 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4839 */
4840 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4841
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004842 if (cp->privacy) {
4843 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4844 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4845 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4846 } else {
4847 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4848 memset(hdev->irk, 0, sizeof(hdev->irk));
4849 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4850 }
4851
4852 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4853 if (err < 0)
4854 goto unlock;
4855
4856 if (changed)
4857 err = new_settings(hdev, sk);
4858
4859unlock:
4860 hci_dev_unlock(hdev);
4861 return err;
4862}
4863
Johan Hedberg41edf162014-02-18 10:19:35 +02004864static bool irk_is_valid(struct mgmt_irk_info *irk)
4865{
4866 switch (irk->addr.type) {
4867 case BDADDR_LE_PUBLIC:
4868 return true;
4869
4870 case BDADDR_LE_RANDOM:
4871 /* Two most significant bits shall be set */
4872 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4873 return false;
4874 return true;
4875 }
4876
4877 return false;
4878}
4879
4880static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4881 u16 len)
4882{
4883 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004884 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4885 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004886 u16 irk_count, expected_len;
4887 int i, err;
4888
4889 BT_DBG("request for %s", hdev->name);
4890
4891 if (!lmp_le_capable(hdev))
4892 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4893 MGMT_STATUS_NOT_SUPPORTED);
4894
4895 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004896 if (irk_count > max_irk_count) {
4897 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4898 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4899 MGMT_STATUS_INVALID_PARAMS);
4900 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004901
4902 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4903 if (expected_len != len) {
4904 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004905 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004906 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4907 MGMT_STATUS_INVALID_PARAMS);
4908 }
4909
4910 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4911
4912 for (i = 0; i < irk_count; i++) {
4913 struct mgmt_irk_info *key = &cp->irks[i];
4914
4915 if (!irk_is_valid(key))
4916 return cmd_status(sk, hdev->id,
4917 MGMT_OP_LOAD_IRKS,
4918 MGMT_STATUS_INVALID_PARAMS);
4919 }
4920
4921 hci_dev_lock(hdev);
4922
4923 hci_smp_irks_clear(hdev);
4924
4925 for (i = 0; i < irk_count; i++) {
4926 struct mgmt_irk_info *irk = &cp->irks[i];
4927 u8 addr_type;
4928
4929 if (irk->addr.type == BDADDR_LE_PUBLIC)
4930 addr_type = ADDR_LE_DEV_PUBLIC;
4931 else
4932 addr_type = ADDR_LE_DEV_RANDOM;
4933
4934 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4935 BDADDR_ANY);
4936 }
4937
4938 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4939
4940 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4941
4942 hci_dev_unlock(hdev);
4943
4944 return err;
4945}
4946
Johan Hedberg3f706b72013-01-20 14:27:16 +02004947static bool ltk_is_valid(struct mgmt_ltk_info *key)
4948{
4949 if (key->master != 0x00 && key->master != 0x01)
4950 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004951
4952 switch (key->addr.type) {
4953 case BDADDR_LE_PUBLIC:
4954 return true;
4955
4956 case BDADDR_LE_RANDOM:
4957 /* Two most significant bits shall be set */
4958 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4959 return false;
4960 return true;
4961 }
4962
4963 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004964}
4965
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004966static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004967 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004968{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004969 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004970 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4971 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004972 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004973 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004974
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004975 BT_DBG("request for %s", hdev->name);
4976
4977 if (!lmp_le_capable(hdev))
4978 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4979 MGMT_STATUS_NOT_SUPPORTED);
4980
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004981 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004982 if (key_count > max_key_count) {
4983 BT_ERR("load_ltks: too big key_count value %u", key_count);
4984 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4985 MGMT_STATUS_INVALID_PARAMS);
4986 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004987
4988 expected_len = sizeof(*cp) + key_count *
4989 sizeof(struct mgmt_ltk_info);
4990 if (expected_len != len) {
4991 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004992 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004993 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02004994 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004995 }
4996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004997 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004998
Johan Hedberg54ad6d82013-01-20 14:27:15 +02004999 for (i = 0; i < key_count; i++) {
5000 struct mgmt_ltk_info *key = &cp->keys[i];
5001
Johan Hedberg3f706b72013-01-20 14:27:16 +02005002 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005003 return cmd_status(sk, hdev->id,
5004 MGMT_OP_LOAD_LONG_TERM_KEYS,
5005 MGMT_STATUS_INVALID_PARAMS);
5006 }
5007
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005008 hci_dev_lock(hdev);
5009
5010 hci_smp_ltks_clear(hdev);
5011
5012 for (i = 0; i < key_count; i++) {
5013 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005014 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005015
5016 if (key->addr.type == BDADDR_LE_PUBLIC)
5017 addr_type = ADDR_LE_DEV_PUBLIC;
5018 else
5019 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005020
Johan Hedberg61b43352014-05-29 19:36:53 +03005021 switch (key->type) {
5022 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005023 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005024 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005025 break;
5026 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005027 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005028 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005029 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005030 case MGMT_LTK_P256_UNAUTH:
5031 authenticated = 0x00;
5032 type = SMP_LTK_P256;
5033 break;
5034 case MGMT_LTK_P256_AUTH:
5035 authenticated = 0x01;
5036 type = SMP_LTK_P256;
5037 break;
5038 case MGMT_LTK_P256_DEBUG:
5039 authenticated = 0x00;
5040 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005041 default:
5042 continue;
5043 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005044
Johan Hedberg35d70272014-02-19 14:57:47 +02005045 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005046 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005047 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005048 }
5049
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005050 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5051 NULL, 0);
5052
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005053 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005054
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005055 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005056}
5057
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005058struct cmd_conn_lookup {
5059 struct hci_conn *conn;
5060 bool valid_tx_power;
5061 u8 mgmt_status;
5062};
5063
5064static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5065{
5066 struct cmd_conn_lookup *match = data;
5067 struct mgmt_cp_get_conn_info *cp;
5068 struct mgmt_rp_get_conn_info rp;
5069 struct hci_conn *conn = cmd->user_data;
5070
5071 if (conn != match->conn)
5072 return;
5073
5074 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5075
5076 memset(&rp, 0, sizeof(rp));
5077 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5078 rp.addr.type = cp->addr.type;
5079
5080 if (!match->mgmt_status) {
5081 rp.rssi = conn->rssi;
5082
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005083 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005084 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005085 rp.max_tx_power = conn->max_tx_power;
5086 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005087 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005088 rp.max_tx_power = HCI_TX_POWER_INVALID;
5089 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005090 }
5091
5092 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5093 match->mgmt_status, &rp, sizeof(rp));
5094
5095 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005096 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005097
5098 mgmt_pending_remove(cmd);
5099}
5100
5101static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5102{
5103 struct hci_cp_read_rssi *cp;
5104 struct hci_conn *conn;
5105 struct cmd_conn_lookup match;
5106 u16 handle;
5107
5108 BT_DBG("status 0x%02x", status);
5109
5110 hci_dev_lock(hdev);
5111
5112 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005113 * otherwise we assume it's not valid. At the moment we assume that
5114 * either both or none of current and max values are valid to keep code
5115 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005116 */
5117 match.valid_tx_power = !status;
5118
5119 /* Commands sent in request are either Read RSSI or Read Transmit Power
5120 * Level so we check which one was last sent to retrieve connection
5121 * handle. Both commands have handle as first parameter so it's safe to
5122 * cast data on the same command struct.
5123 *
5124 * First command sent is always Read RSSI and we fail only if it fails.
5125 * In other case we simply override error to indicate success as we
5126 * already remembered if TX power value is actually valid.
5127 */
5128 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5129 if (!cp) {
5130 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5131 status = 0;
5132 }
5133
5134 if (!cp) {
5135 BT_ERR("invalid sent_cmd in response");
5136 goto unlock;
5137 }
5138
5139 handle = __le16_to_cpu(cp->handle);
5140 conn = hci_conn_hash_lookup_handle(hdev, handle);
5141 if (!conn) {
5142 BT_ERR("unknown handle (%d) in response", handle);
5143 goto unlock;
5144 }
5145
5146 match.conn = conn;
5147 match.mgmt_status = mgmt_status(status);
5148
5149 /* Cache refresh is complete, now reply for mgmt request for given
5150 * connection only.
5151 */
5152 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5153 get_conn_info_complete, &match);
5154
5155unlock:
5156 hci_dev_unlock(hdev);
5157}
5158
5159static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5160 u16 len)
5161{
5162 struct mgmt_cp_get_conn_info *cp = data;
5163 struct mgmt_rp_get_conn_info rp;
5164 struct hci_conn *conn;
5165 unsigned long conn_info_age;
5166 int err = 0;
5167
5168 BT_DBG("%s", hdev->name);
5169
5170 memset(&rp, 0, sizeof(rp));
5171 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5172 rp.addr.type = cp->addr.type;
5173
5174 if (!bdaddr_type_is_valid(cp->addr.type))
5175 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5176 MGMT_STATUS_INVALID_PARAMS,
5177 &rp, sizeof(rp));
5178
5179 hci_dev_lock(hdev);
5180
5181 if (!hdev_is_powered(hdev)) {
5182 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5183 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5184 goto unlock;
5185 }
5186
5187 if (cp->addr.type == BDADDR_BREDR)
5188 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5189 &cp->addr.bdaddr);
5190 else
5191 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5192
5193 if (!conn || conn->state != BT_CONNECTED) {
5194 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5195 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5196 goto unlock;
5197 }
5198
5199 /* To avoid client trying to guess when to poll again for information we
5200 * calculate conn info age as random value between min/max set in hdev.
5201 */
5202 conn_info_age = hdev->conn_info_min_age +
5203 prandom_u32_max(hdev->conn_info_max_age -
5204 hdev->conn_info_min_age);
5205
5206 /* Query controller to refresh cached values if they are too old or were
5207 * never read.
5208 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005209 if (time_after(jiffies, conn->conn_info_timestamp +
5210 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005211 !conn->conn_info_timestamp) {
5212 struct hci_request req;
5213 struct hci_cp_read_tx_power req_txp_cp;
5214 struct hci_cp_read_rssi req_rssi_cp;
5215 struct pending_cmd *cmd;
5216
5217 hci_req_init(&req, hdev);
5218 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5219 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5220 &req_rssi_cp);
5221
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005222 /* For LE links TX power does not change thus we don't need to
5223 * query for it once value is known.
5224 */
5225 if (!bdaddr_type_is_le(cp->addr.type) ||
5226 conn->tx_power == HCI_TX_POWER_INVALID) {
5227 req_txp_cp.handle = cpu_to_le16(conn->handle);
5228 req_txp_cp.type = 0x00;
5229 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5230 sizeof(req_txp_cp), &req_txp_cp);
5231 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005232
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005233 /* Max TX power needs to be read only once per connection */
5234 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5235 req_txp_cp.handle = cpu_to_le16(conn->handle);
5236 req_txp_cp.type = 0x01;
5237 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5238 sizeof(req_txp_cp), &req_txp_cp);
5239 }
5240
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005241 err = hci_req_run(&req, conn_info_refresh_complete);
5242 if (err < 0)
5243 goto unlock;
5244
5245 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5246 data, len);
5247 if (!cmd) {
5248 err = -ENOMEM;
5249 goto unlock;
5250 }
5251
5252 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005253 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005254
5255 conn->conn_info_timestamp = jiffies;
5256 } else {
5257 /* Cache is valid, just reply with values cached in hci_conn */
5258 rp.rssi = conn->rssi;
5259 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005260 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005261
5262 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5263 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5264 }
5265
5266unlock:
5267 hci_dev_unlock(hdev);
5268 return err;
5269}
5270
Johan Hedberg95868422014-06-28 17:54:07 +03005271static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5272{
5273 struct mgmt_cp_get_clock_info *cp;
5274 struct mgmt_rp_get_clock_info rp;
5275 struct hci_cp_read_clock *hci_cp;
5276 struct pending_cmd *cmd;
5277 struct hci_conn *conn;
5278
5279 BT_DBG("%s status %u", hdev->name, status);
5280
5281 hci_dev_lock(hdev);
5282
5283 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5284 if (!hci_cp)
5285 goto unlock;
5286
5287 if (hci_cp->which) {
5288 u16 handle = __le16_to_cpu(hci_cp->handle);
5289 conn = hci_conn_hash_lookup_handle(hdev, handle);
5290 } else {
5291 conn = NULL;
5292 }
5293
5294 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5295 if (!cmd)
5296 goto unlock;
5297
5298 cp = cmd->param;
5299
5300 memset(&rp, 0, sizeof(rp));
5301 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5302
5303 if (status)
5304 goto send_rsp;
5305
5306 rp.local_clock = cpu_to_le32(hdev->clock);
5307
5308 if (conn) {
5309 rp.piconet_clock = cpu_to_le32(conn->clock);
5310 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5311 }
5312
5313send_rsp:
5314 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5315 &rp, sizeof(rp));
5316 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005317 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005318 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005319 hci_conn_put(conn);
5320 }
Johan Hedberg95868422014-06-28 17:54:07 +03005321
5322unlock:
5323 hci_dev_unlock(hdev);
5324}
5325
5326static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5327 u16 len)
5328{
5329 struct mgmt_cp_get_clock_info *cp = data;
5330 struct mgmt_rp_get_clock_info rp;
5331 struct hci_cp_read_clock hci_cp;
5332 struct pending_cmd *cmd;
5333 struct hci_request req;
5334 struct hci_conn *conn;
5335 int err;
5336
5337 BT_DBG("%s", hdev->name);
5338
5339 memset(&rp, 0, sizeof(rp));
5340 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5341 rp.addr.type = cp->addr.type;
5342
5343 if (cp->addr.type != BDADDR_BREDR)
5344 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5345 MGMT_STATUS_INVALID_PARAMS,
5346 &rp, sizeof(rp));
5347
5348 hci_dev_lock(hdev);
5349
5350 if (!hdev_is_powered(hdev)) {
5351 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5352 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5353 goto unlock;
5354 }
5355
5356 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5357 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5358 &cp->addr.bdaddr);
5359 if (!conn || conn->state != BT_CONNECTED) {
5360 err = cmd_complete(sk, hdev->id,
5361 MGMT_OP_GET_CLOCK_INFO,
5362 MGMT_STATUS_NOT_CONNECTED,
5363 &rp, sizeof(rp));
5364 goto unlock;
5365 }
5366 } else {
5367 conn = NULL;
5368 }
5369
5370 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5371 if (!cmd) {
5372 err = -ENOMEM;
5373 goto unlock;
5374 }
5375
5376 hci_req_init(&req, hdev);
5377
5378 memset(&hci_cp, 0, sizeof(hci_cp));
5379 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5380
5381 if (conn) {
5382 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005383 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005384
5385 hci_cp.handle = cpu_to_le16(conn->handle);
5386 hci_cp.which = 0x01; /* Piconet clock */
5387 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5388 }
5389
5390 err = hci_req_run(&req, get_clock_info_complete);
5391 if (err < 0)
5392 mgmt_pending_remove(cmd);
5393
5394unlock:
5395 hci_dev_unlock(hdev);
5396 return err;
5397}
5398
Marcel Holtmann8afef092014-06-29 22:28:34 +02005399static void device_added(struct sock *sk, struct hci_dev *hdev,
5400 bdaddr_t *bdaddr, u8 type, u8 action)
5401{
5402 struct mgmt_ev_device_added ev;
5403
5404 bacpy(&ev.addr.bdaddr, bdaddr);
5405 ev.addr.type = type;
5406 ev.action = action;
5407
5408 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5409}
5410
Marcel Holtmann2faade52014-06-29 19:44:03 +02005411static int add_device(struct sock *sk, struct hci_dev *hdev,
5412 void *data, u16 len)
5413{
5414 struct mgmt_cp_add_device *cp = data;
5415 u8 auto_conn, addr_type;
5416 int err;
5417
5418 BT_DBG("%s", hdev->name);
5419
Johan Hedberg66593582014-07-09 12:59:14 +03005420 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005421 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5422 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5423 MGMT_STATUS_INVALID_PARAMS,
5424 &cp->addr, sizeof(cp->addr));
5425
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005426 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005427 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5428 MGMT_STATUS_INVALID_PARAMS,
5429 &cp->addr, sizeof(cp->addr));
5430
5431 hci_dev_lock(hdev);
5432
Johan Hedberg66593582014-07-09 12:59:14 +03005433 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005434 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005435 if (cp->action != 0x01) {
5436 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5437 MGMT_STATUS_INVALID_PARAMS,
5438 &cp->addr, sizeof(cp->addr));
5439 goto unlock;
5440 }
5441
5442 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5443 cp->addr.type);
5444 if (err)
5445 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005446
Johan Hedberg432df052014-08-01 11:13:31 +03005447 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005448
Johan Hedberg66593582014-07-09 12:59:14 +03005449 goto added;
5450 }
5451
Marcel Holtmann2faade52014-06-29 19:44:03 +02005452 if (cp->addr.type == BDADDR_LE_PUBLIC)
5453 addr_type = ADDR_LE_DEV_PUBLIC;
5454 else
5455 addr_type = ADDR_LE_DEV_RANDOM;
5456
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005457 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005458 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005459 else if (cp->action == 0x01)
5460 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005461 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005462 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005463
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005464 /* If the connection parameters don't exist for this device,
5465 * they will be created and configured with defaults.
5466 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005467 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5468 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005469 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5470 MGMT_STATUS_FAILED,
5471 &cp->addr, sizeof(cp->addr));
5472 goto unlock;
5473 }
5474
Johan Hedberg66593582014-07-09 12:59:14 +03005475added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005476 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5477
Marcel Holtmann2faade52014-06-29 19:44:03 +02005478 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5479 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5480
5481unlock:
5482 hci_dev_unlock(hdev);
5483 return err;
5484}
5485
Marcel Holtmann8afef092014-06-29 22:28:34 +02005486static void device_removed(struct sock *sk, struct hci_dev *hdev,
5487 bdaddr_t *bdaddr, u8 type)
5488{
5489 struct mgmt_ev_device_removed ev;
5490
5491 bacpy(&ev.addr.bdaddr, bdaddr);
5492 ev.addr.type = type;
5493
5494 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5495}
5496
Marcel Holtmann2faade52014-06-29 19:44:03 +02005497static int remove_device(struct sock *sk, struct hci_dev *hdev,
5498 void *data, u16 len)
5499{
5500 struct mgmt_cp_remove_device *cp = data;
5501 int err;
5502
5503 BT_DBG("%s", hdev->name);
5504
5505 hci_dev_lock(hdev);
5506
5507 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005508 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005509 u8 addr_type;
5510
Johan Hedberg66593582014-07-09 12:59:14 +03005511 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005512 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5513 MGMT_STATUS_INVALID_PARAMS,
5514 &cp->addr, sizeof(cp->addr));
5515 goto unlock;
5516 }
5517
Johan Hedberg66593582014-07-09 12:59:14 +03005518 if (cp->addr.type == BDADDR_BREDR) {
5519 err = hci_bdaddr_list_del(&hdev->whitelist,
5520 &cp->addr.bdaddr,
5521 cp->addr.type);
5522 if (err) {
5523 err = cmd_complete(sk, hdev->id,
5524 MGMT_OP_REMOVE_DEVICE,
5525 MGMT_STATUS_INVALID_PARAMS,
5526 &cp->addr, sizeof(cp->addr));
5527 goto unlock;
5528 }
5529
Johan Hedberg432df052014-08-01 11:13:31 +03005530 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005531
Johan Hedberg66593582014-07-09 12:59:14 +03005532 device_removed(sk, hdev, &cp->addr.bdaddr,
5533 cp->addr.type);
5534 goto complete;
5535 }
5536
Marcel Holtmann2faade52014-06-29 19:44:03 +02005537 if (cp->addr.type == BDADDR_LE_PUBLIC)
5538 addr_type = ADDR_LE_DEV_PUBLIC;
5539 else
5540 addr_type = ADDR_LE_DEV_RANDOM;
5541
Johan Hedbergc71593d2014-07-02 17:37:28 +03005542 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5543 addr_type);
5544 if (!params) {
5545 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5546 MGMT_STATUS_INVALID_PARAMS,
5547 &cp->addr, sizeof(cp->addr));
5548 goto unlock;
5549 }
5550
5551 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5552 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5553 MGMT_STATUS_INVALID_PARAMS,
5554 &cp->addr, sizeof(cp->addr));
5555 goto unlock;
5556 }
5557
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005558 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005559 list_del(&params->list);
5560 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005561 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005562
5563 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005564 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005565 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005566 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005567
Marcel Holtmann2faade52014-06-29 19:44:03 +02005568 if (cp->addr.type) {
5569 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5570 MGMT_STATUS_INVALID_PARAMS,
5571 &cp->addr, sizeof(cp->addr));
5572 goto unlock;
5573 }
5574
Johan Hedberg66593582014-07-09 12:59:14 +03005575 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5576 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5577 list_del(&b->list);
5578 kfree(b);
5579 }
5580
Johan Hedberg432df052014-08-01 11:13:31 +03005581 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005582
Johan Hedberg19de0822014-07-06 13:06:51 +03005583 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5584 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5585 continue;
5586 device_removed(sk, hdev, &p->addr, p->addr_type);
5587 list_del(&p->action);
5588 list_del(&p->list);
5589 kfree(p);
5590 }
5591
5592 BT_DBG("All LE connection parameters were removed");
5593
5594 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005595 }
5596
Johan Hedberg66593582014-07-09 12:59:14 +03005597complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005598 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5599 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5600
5601unlock:
5602 hci_dev_unlock(hdev);
5603 return err;
5604}
5605
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005606static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5607 u16 len)
5608{
5609 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005610 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5611 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005612 u16 param_count, expected_len;
5613 int i;
5614
5615 if (!lmp_le_capable(hdev))
5616 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5617 MGMT_STATUS_NOT_SUPPORTED);
5618
5619 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005620 if (param_count > max_param_count) {
5621 BT_ERR("load_conn_param: too big param_count value %u",
5622 param_count);
5623 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5624 MGMT_STATUS_INVALID_PARAMS);
5625 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005626
5627 expected_len = sizeof(*cp) + param_count *
5628 sizeof(struct mgmt_conn_param);
5629 if (expected_len != len) {
5630 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5631 expected_len, len);
5632 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5633 MGMT_STATUS_INVALID_PARAMS);
5634 }
5635
5636 BT_DBG("%s param_count %u", hdev->name, param_count);
5637
5638 hci_dev_lock(hdev);
5639
5640 hci_conn_params_clear_disabled(hdev);
5641
5642 for (i = 0; i < param_count; i++) {
5643 struct mgmt_conn_param *param = &cp->params[i];
5644 struct hci_conn_params *hci_param;
5645 u16 min, max, latency, timeout;
5646 u8 addr_type;
5647
5648 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5649 param->addr.type);
5650
5651 if (param->addr.type == BDADDR_LE_PUBLIC) {
5652 addr_type = ADDR_LE_DEV_PUBLIC;
5653 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5654 addr_type = ADDR_LE_DEV_RANDOM;
5655 } else {
5656 BT_ERR("Ignoring invalid connection parameters");
5657 continue;
5658 }
5659
5660 min = le16_to_cpu(param->min_interval);
5661 max = le16_to_cpu(param->max_interval);
5662 latency = le16_to_cpu(param->latency);
5663 timeout = le16_to_cpu(param->timeout);
5664
5665 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5666 min, max, latency, timeout);
5667
5668 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5669 BT_ERR("Ignoring invalid connection parameters");
5670 continue;
5671 }
5672
5673 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5674 addr_type);
5675 if (!hci_param) {
5676 BT_ERR("Failed to add connection parameters");
5677 continue;
5678 }
5679
5680 hci_param->conn_min_interval = min;
5681 hci_param->conn_max_interval = max;
5682 hci_param->conn_latency = latency;
5683 hci_param->supervision_timeout = timeout;
5684 }
5685
5686 hci_dev_unlock(hdev);
5687
5688 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5689}
5690
Marcel Holtmanndbece372014-07-04 18:11:55 +02005691static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5692 void *data, u16 len)
5693{
5694 struct mgmt_cp_set_external_config *cp = data;
5695 bool changed;
5696 int err;
5697
5698 BT_DBG("%s", hdev->name);
5699
5700 if (hdev_is_powered(hdev))
5701 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5702 MGMT_STATUS_REJECTED);
5703
5704 if (cp->config != 0x00 && cp->config != 0x01)
5705 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5706 MGMT_STATUS_INVALID_PARAMS);
5707
5708 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5709 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5710 MGMT_STATUS_NOT_SUPPORTED);
5711
5712 hci_dev_lock(hdev);
5713
5714 if (cp->config)
5715 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5716 &hdev->dev_flags);
5717 else
5718 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5719 &hdev->dev_flags);
5720
5721 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5722 if (err < 0)
5723 goto unlock;
5724
5725 if (!changed)
5726 goto unlock;
5727
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005728 err = new_options(hdev, sk);
5729
Marcel Holtmanndbece372014-07-04 18:11:55 +02005730 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5731 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005732
5733 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5734 set_bit(HCI_CONFIG, &hdev->dev_flags);
5735 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5736
5737 queue_work(hdev->req_workqueue, &hdev->power_on);
5738 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005739 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005740 mgmt_index_added(hdev);
5741 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005742 }
5743
5744unlock:
5745 hci_dev_unlock(hdev);
5746 return err;
5747}
5748
Marcel Holtmann9713c172014-07-06 12:11:15 +02005749static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5750 void *data, u16 len)
5751{
5752 struct mgmt_cp_set_public_address *cp = data;
5753 bool changed;
5754 int err;
5755
5756 BT_DBG("%s", hdev->name);
5757
5758 if (hdev_is_powered(hdev))
5759 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5760 MGMT_STATUS_REJECTED);
5761
5762 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5763 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5764 MGMT_STATUS_INVALID_PARAMS);
5765
5766 if (!hdev->set_bdaddr)
5767 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5768 MGMT_STATUS_NOT_SUPPORTED);
5769
5770 hci_dev_lock(hdev);
5771
5772 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5773 bacpy(&hdev->public_addr, &cp->bdaddr);
5774
5775 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5776 if (err < 0)
5777 goto unlock;
5778
5779 if (!changed)
5780 goto unlock;
5781
5782 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5783 err = new_options(hdev, sk);
5784
5785 if (is_configured(hdev)) {
5786 mgmt_index_removed(hdev);
5787
5788 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5789
5790 set_bit(HCI_CONFIG, &hdev->dev_flags);
5791 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5792
5793 queue_work(hdev->req_workqueue, &hdev->power_on);
5794 }
5795
5796unlock:
5797 hci_dev_unlock(hdev);
5798 return err;
5799}
5800
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005801static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005802 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5803 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005804 bool var_len;
5805 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005806} mgmt_handlers[] = {
5807 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005808 { read_version, false, MGMT_READ_VERSION_SIZE },
5809 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5810 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5811 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5812 { set_powered, false, MGMT_SETTING_SIZE },
5813 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5814 { set_connectable, false, MGMT_SETTING_SIZE },
5815 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005816 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005817 { set_link_security, false, MGMT_SETTING_SIZE },
5818 { set_ssp, false, MGMT_SETTING_SIZE },
5819 { set_hs, false, MGMT_SETTING_SIZE },
5820 { set_le, false, MGMT_SETTING_SIZE },
5821 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5822 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5823 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5824 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5825 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5826 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5827 { disconnect, false, MGMT_DISCONNECT_SIZE },
5828 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5829 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5830 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5831 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5832 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5833 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5834 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5835 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5836 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5837 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5838 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5839 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005840 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005841 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5842 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5843 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5844 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5845 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5846 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005847 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005848 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005849 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005850 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005851 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005852 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005853 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005854 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005855 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005856 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005857 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005858 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5859 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005860 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5861 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005862 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005863 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005864 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005865 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005866};
5867
Johan Hedberg03811012010-12-08 00:21:06 +02005868int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5869{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005870 void *buf;
5871 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005872 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005873 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005874 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005875 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005876 int err;
5877
5878 BT_DBG("got %zu bytes", msglen);
5879
5880 if (msglen < sizeof(*hdr))
5881 return -EINVAL;
5882
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005883 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005884 if (!buf)
5885 return -ENOMEM;
5886
5887 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5888 err = -EFAULT;
5889 goto done;
5890 }
5891
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005892 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005893 opcode = __le16_to_cpu(hdr->opcode);
5894 index = __le16_to_cpu(hdr->index);
5895 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005896
5897 if (len != msglen - sizeof(*hdr)) {
5898 err = -EINVAL;
5899 goto done;
5900 }
5901
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005902 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005903 hdev = hci_dev_get(index);
5904 if (!hdev) {
5905 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005906 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005907 goto done;
5908 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005909
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005910 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005911 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005912 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005913 err = cmd_status(sk, index, opcode,
5914 MGMT_STATUS_INVALID_INDEX);
5915 goto done;
5916 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005917
5918 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005919 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005920 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5921 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005922 err = cmd_status(sk, index, opcode,
5923 MGMT_STATUS_INVALID_INDEX);
5924 goto done;
5925 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005926 }
5927
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005928 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005929 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005930 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005931 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005932 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005933 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005934 }
5935
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005936 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5937 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5938 err = cmd_status(sk, index, opcode,
5939 MGMT_STATUS_INVALID_INDEX);
5940 goto done;
5941 }
5942
5943 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5944 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005945 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005946 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005947 goto done;
5948 }
5949
Johan Hedbergbe22b542012-03-01 22:24:41 +02005950 handler = &mgmt_handlers[opcode];
5951
5952 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005953 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005954 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005955 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005956 goto done;
5957 }
5958
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005959 if (hdev)
5960 mgmt_init_hdev(sk, hdev);
5961
5962 cp = buf + sizeof(*hdr);
5963
Johan Hedbergbe22b542012-03-01 22:24:41 +02005964 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005965 if (err < 0)
5966 goto done;
5967
Johan Hedberg03811012010-12-08 00:21:06 +02005968 err = msglen;
5969
5970done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005971 if (hdev)
5972 hci_dev_put(hdev);
5973
Johan Hedberg03811012010-12-08 00:21:06 +02005974 kfree(buf);
5975 return err;
5976}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005977
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005978void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005979{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005980 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005981 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005982
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005983 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5984 return;
5985
5986 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5987 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
5988 else
5989 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005990}
5991
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005992void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005993{
Johan Hedberg5f159032012-03-02 03:13:19 +02005994 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02005995
Marcel Holtmann1514b892013-10-06 08:25:01 -07005996 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005997 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005998
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005999 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6000 return;
6001
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006002 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006003
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02006004 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6005 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6006 else
6007 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006008}
6009
Andre Guedes6046dc32014-02-26 20:21:51 -03006010/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006011static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006012{
6013 struct hci_conn_params *p;
6014
6015 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006016 /* Needed for AUTO_OFF case where might not "really"
6017 * have been powered off.
6018 */
6019 list_del_init(&p->action);
6020
6021 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006022 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006023 case HCI_AUTO_CONN_ALWAYS:
6024 list_add(&p->action, &hdev->pend_le_conns);
6025 break;
6026 case HCI_AUTO_CONN_REPORT:
6027 list_add(&p->action, &hdev->pend_le_reports);
6028 break;
6029 default:
6030 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006031 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006032 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006033
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006034 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006035}
6036
Johan Hedberg229ab392013-03-15 17:06:53 -05006037static void powered_complete(struct hci_dev *hdev, u8 status)
6038{
6039 struct cmd_lookup match = { NULL, hdev };
6040
6041 BT_DBG("status 0x%02x", status);
6042
6043 hci_dev_lock(hdev);
6044
Johan Hedbergd7347f32014-07-04 12:37:23 +03006045 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006046
Johan Hedberg229ab392013-03-15 17:06:53 -05006047 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6048
6049 new_settings(hdev, match.sk);
6050
6051 hci_dev_unlock(hdev);
6052
6053 if (match.sk)
6054 sock_put(match.sk);
6055}
6056
Johan Hedberg70da6242013-03-15 17:06:51 -05006057static int powered_update_hci(struct hci_dev *hdev)
6058{
Johan Hedberg890ea892013-03-15 17:06:52 -05006059 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006060 u8 link_sec;
6061
Johan Hedberg890ea892013-03-15 17:06:52 -05006062 hci_req_init(&req, hdev);
6063
Johan Hedberg70da6242013-03-15 17:06:51 -05006064 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6065 !lmp_host_ssp_capable(hdev)) {
6066 u8 ssp = 1;
6067
Johan Hedberg890ea892013-03-15 17:06:52 -05006068 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006069 }
6070
Johan Hedbergc73eee92013-04-19 18:35:21 +03006071 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6072 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006073 struct hci_cp_write_le_host_supported cp;
6074
Marcel Holtmann32226e42014-07-24 20:04:16 +02006075 cp.le = 0x01;
6076 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006077
6078 /* Check first if we already have the right
6079 * host state (host features set)
6080 */
6081 if (cp.le != lmp_host_le_capable(hdev) ||
6082 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006083 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6084 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006085 }
6086
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006087 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006088 /* Make sure the controller has a good default for
6089 * advertising data. This also applies to the case
6090 * where BR/EDR was toggled during the AUTO_OFF phase.
6091 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006092 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006093 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006094 update_scan_rsp_data(&req);
6095 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006096
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006097 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6098 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006099 }
6100
Johan Hedberg70da6242013-03-15 17:06:51 -05006101 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6102 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006103 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6104 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006105
6106 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006107 write_fast_connectable(&req, false);
6108 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006109 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006110 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006111 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006112 }
6113
Johan Hedberg229ab392013-03-15 17:06:53 -05006114 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006115}
6116
Johan Hedberg744cf192011-11-08 20:40:14 +02006117int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006118{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006119 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006120 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6121 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006122 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006123
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006124 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6125 return 0;
6126
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006127 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006128 if (powered_update_hci(hdev) == 0)
6129 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006130
Johan Hedberg229ab392013-03-15 17:06:53 -05006131 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6132 &match);
6133 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006134 }
6135
Johan Hedberg229ab392013-03-15 17:06:53 -05006136 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006137 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006138
6139 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6140 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6141 zero_cod, sizeof(zero_cod), NULL);
6142
6143new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006144 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006145
6146 if (match.sk)
6147 sock_put(match.sk);
6148
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006149 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006150}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006151
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006152void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006153{
6154 struct pending_cmd *cmd;
6155 u8 status;
6156
6157 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6158 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006159 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006160
6161 if (err == -ERFKILL)
6162 status = MGMT_STATUS_RFKILLED;
6163 else
6164 status = MGMT_STATUS_FAILED;
6165
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006166 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006167
6168 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006169}
6170
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006171void mgmt_discoverable_timeout(struct hci_dev *hdev)
6172{
6173 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006174
6175 hci_dev_lock(hdev);
6176
6177 /* When discoverable timeout triggers, then just make sure
6178 * the limited discoverable flag is cleared. Even in the case
6179 * of a timeout triggered from general discoverable, it is
6180 * safe to unconditionally clear the flag.
6181 */
6182 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006183 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006184
6185 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006186 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6187 u8 scan = SCAN_PAGE;
6188 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6189 sizeof(scan), &scan);
6190 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006191 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006192 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006193 hci_req_run(&req, NULL);
6194
6195 hdev->discov_timeout = 0;
6196
Johan Hedberg9a43e252013-10-20 19:00:07 +03006197 new_settings(hdev, NULL);
6198
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006199 hci_dev_unlock(hdev);
6200}
6201
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006202void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6203 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006204{
Johan Hedberg86742e12011-11-07 23:13:38 +02006205 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006206
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006207 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006208
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006209 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006210 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006211 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006212 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006213 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006214 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006215
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006216 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006217}
Johan Hedbergf7520542011-01-20 12:34:39 +02006218
Johan Hedbergd7b25452014-05-23 13:19:53 +03006219static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6220{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006221 switch (ltk->type) {
6222 case SMP_LTK:
6223 case SMP_LTK_SLAVE:
6224 if (ltk->authenticated)
6225 return MGMT_LTK_AUTHENTICATED;
6226 return MGMT_LTK_UNAUTHENTICATED;
6227 case SMP_LTK_P256:
6228 if (ltk->authenticated)
6229 return MGMT_LTK_P256_AUTH;
6230 return MGMT_LTK_P256_UNAUTH;
6231 case SMP_LTK_P256_DEBUG:
6232 return MGMT_LTK_P256_DEBUG;
6233 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006234
6235 return MGMT_LTK_UNAUTHENTICATED;
6236}
6237
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006238void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006239{
6240 struct mgmt_ev_new_long_term_key ev;
6241
6242 memset(&ev, 0, sizeof(ev));
6243
Marcel Holtmann5192d302014-02-19 17:11:58 -08006244 /* Devices using resolvable or non-resolvable random addresses
6245 * without providing an indentity resolving key don't require
6246 * to store long term keys. Their addresses will change the
6247 * next time around.
6248 *
6249 * Only when a remote device provides an identity address
6250 * make sure the long term key is stored. If the remote
6251 * identity is known, the long term keys are internally
6252 * mapped to the identity address. So allow static random
6253 * and public addresses here.
6254 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006255 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6256 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6257 ev.store_hint = 0x00;
6258 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006259 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006260
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006261 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006262 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006263 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006264 ev.key.enc_size = key->enc_size;
6265 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006266 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006267
Johan Hedberg2ceba532014-06-16 19:25:16 +03006268 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006269 ev.key.master = 1;
6270
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006271 memcpy(ev.key.val, key->val, sizeof(key->val));
6272
Marcel Holtmann083368f2013-10-15 14:26:29 -07006273 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006274}
6275
Johan Hedberg95fbac82014-02-19 15:18:31 +02006276void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6277{
6278 struct mgmt_ev_new_irk ev;
6279
6280 memset(&ev, 0, sizeof(ev));
6281
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006282 /* For identity resolving keys from devices that are already
6283 * using a public address or static random address, do not
6284 * ask for storing this key. The identity resolving key really
6285 * is only mandatory for devices using resovlable random
6286 * addresses.
6287 *
6288 * Storing all identity resolving keys has the downside that
6289 * they will be also loaded on next boot of they system. More
6290 * identity resolving keys, means more time during scanning is
6291 * needed to actually resolve these addresses.
6292 */
6293 if (bacmp(&irk->rpa, BDADDR_ANY))
6294 ev.store_hint = 0x01;
6295 else
6296 ev.store_hint = 0x00;
6297
Johan Hedberg95fbac82014-02-19 15:18:31 +02006298 bacpy(&ev.rpa, &irk->rpa);
6299 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6300 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6301 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6302
6303 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6304}
6305
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006306void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6307 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006308{
6309 struct mgmt_ev_new_csrk ev;
6310
6311 memset(&ev, 0, sizeof(ev));
6312
6313 /* Devices using resolvable or non-resolvable random addresses
6314 * without providing an indentity resolving key don't require
6315 * to store signature resolving keys. Their addresses will change
6316 * the next time around.
6317 *
6318 * Only when a remote device provides an identity address
6319 * make sure the signature resolving key is stored. So allow
6320 * static random and public addresses here.
6321 */
6322 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6323 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6324 ev.store_hint = 0x00;
6325 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006326 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006327
6328 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6329 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6330 ev.key.master = csrk->master;
6331 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6332
6333 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6334}
6335
Andre Guedesffb5a8272014-07-01 18:10:11 -03006336void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006337 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6338 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006339{
6340 struct mgmt_ev_new_conn_param ev;
6341
Johan Hedbergc103aea2014-07-02 17:37:34 +03006342 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6343 return;
6344
Andre Guedesffb5a8272014-07-01 18:10:11 -03006345 memset(&ev, 0, sizeof(ev));
6346 bacpy(&ev.addr.bdaddr, bdaddr);
6347 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006348 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006349 ev.min_interval = cpu_to_le16(min_interval);
6350 ev.max_interval = cpu_to_le16(max_interval);
6351 ev.latency = cpu_to_le16(latency);
6352 ev.timeout = cpu_to_le16(timeout);
6353
6354 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6355}
6356
Marcel Holtmann94933992013-10-15 10:26:39 -07006357static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6358 u8 data_len)
6359{
6360 eir[eir_len++] = sizeof(type) + data_len;
6361 eir[eir_len++] = type;
6362 memcpy(&eir[eir_len], data, data_len);
6363 eir_len += data_len;
6364
6365 return eir_len;
6366}
6367
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006368void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6369 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006370{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006371 char buf[512];
6372 struct mgmt_ev_device_connected *ev = (void *) buf;
6373 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006374
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006375 bacpy(&ev->addr.bdaddr, &conn->dst);
6376 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006377
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006378 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006379
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006380 /* We must ensure that the EIR Data fields are ordered and
6381 * unique. Keep it simple for now and avoid the problem by not
6382 * adding any BR/EDR data to the LE adv.
6383 */
6384 if (conn->le_adv_data_len > 0) {
6385 memcpy(&ev->eir[eir_len],
6386 conn->le_adv_data, conn->le_adv_data_len);
6387 eir_len = conn->le_adv_data_len;
6388 } else {
6389 if (name_len > 0)
6390 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6391 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006392
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006393 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006394 eir_len = eir_append_data(ev->eir, eir_len,
6395 EIR_CLASS_OF_DEV,
6396 conn->dev_class, 3);
6397 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006398
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006399 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006400
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006401 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6402 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006403}
6404
Johan Hedberg8962ee72011-01-20 12:40:27 +02006405static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6406{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006407 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006408
Johan Hedbergf5818c22014-12-05 13:36:02 +02006409 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006410
6411 *sk = cmd->sk;
6412 sock_hold(*sk);
6413
Johan Hedberga664b5b2011-02-19 12:06:02 -03006414 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006415}
6416
Johan Hedberg124f6e32012-02-09 13:50:12 +02006417static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006418{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006419 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006420 struct mgmt_cp_unpair_device *cp = cmd->param;
6421 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006422
6423 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006424 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6425 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006426
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006427 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6428
Johan Hedbergaee9b212012-02-18 15:07:59 +02006429 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006430
6431 mgmt_pending_remove(cmd);
6432}
6433
Johan Hedberg84c61d92014-08-01 11:13:30 +03006434bool mgmt_powering_down(struct hci_dev *hdev)
6435{
6436 struct pending_cmd *cmd;
6437 struct mgmt_mode *cp;
6438
6439 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6440 if (!cmd)
6441 return false;
6442
6443 cp = cmd->param;
6444 if (!cp->val)
6445 return true;
6446
6447 return false;
6448}
6449
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006450void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006451 u8 link_type, u8 addr_type, u8 reason,
6452 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006453{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006454 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006455 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006456
Johan Hedberg84c61d92014-08-01 11:13:30 +03006457 /* The connection is still in hci_conn_hash so test for 1
6458 * instead of 0 to know if this is the last one.
6459 */
6460 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6461 cancel_delayed_work(&hdev->power_off);
6462 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006463 }
6464
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006465 if (!mgmt_connected)
6466 return;
6467
Andre Guedes57eb7762013-10-30 19:01:41 -03006468 if (link_type != ACL_LINK && link_type != LE_LINK)
6469 return;
6470
Johan Hedberg744cf192011-11-08 20:40:14 +02006471 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006472
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006473 bacpy(&ev.addr.bdaddr, bdaddr);
6474 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6475 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006476
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006477 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006478
6479 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006480 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006481
Johan Hedberg124f6e32012-02-09 13:50:12 +02006482 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006483 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006484}
6485
Marcel Holtmann78929242013-10-06 23:55:47 -07006486void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6487 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006488{
Andre Guedes3655bba2013-10-30 19:01:40 -03006489 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6490 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006491 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006492
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006493 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6494 hdev);
6495
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006496 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006497 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006498 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006499
Andre Guedes3655bba2013-10-30 19:01:40 -03006500 cp = cmd->param;
6501
6502 if (bacmp(bdaddr, &cp->addr.bdaddr))
6503 return;
6504
6505 if (cp->addr.type != bdaddr_type)
6506 return;
6507
Johan Hedbergf5818c22014-12-05 13:36:02 +02006508 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006509 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006510}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006511
Marcel Holtmann445608d2013-10-06 23:55:48 -07006512void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6513 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006514{
6515 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006516
Johan Hedberg84c61d92014-08-01 11:13:30 +03006517 /* The connection is still in hci_conn_hash so test for 1
6518 * instead of 0 to know if this is the last one.
6519 */
6520 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6521 cancel_delayed_work(&hdev->power_off);
6522 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006523 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006524
Johan Hedberg4c659c32011-11-07 23:13:39 +02006525 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006526 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006527 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006528
Marcel Holtmann445608d2013-10-06 23:55:48 -07006529 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006530}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006531
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006532void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006533{
6534 struct mgmt_ev_pin_code_request ev;
6535
Johan Hedbergd8457692012-02-17 14:24:57 +02006536 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006537 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006538 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006539
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006540 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006541}
6542
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006543void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6544 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006545{
6546 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006547 struct mgmt_rp_pin_code_reply rp;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006548
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006549 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006550 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006551 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006552
Johan Hedbergd8457692012-02-17 14:24:57 +02006553 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006554 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006555
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006556 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
6557 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006558
Johan Hedberga664b5b2011-02-19 12:06:02 -03006559 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006560}
6561
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006562void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6563 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006564{
6565 struct pending_cmd *cmd;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006566 struct mgmt_rp_pin_code_reply rp;
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 Hedbergd8457692012-02-17 14:24:57 +02006572 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006573 rp.addr.type = BDADDR_BREDR;
Johan Hedbergac56fb12011-02-19 12:05:59 -03006574
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006575 cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
6576 mgmt_status(status), &rp, sizeof(rp));
Johan Hedberg980e1a52011-01-22 06:10:07 +02006577
Johan Hedberga664b5b2011-02-19 12:06:02 -03006578 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006579}
Johan Hedberga5c29682011-02-19 12:05:57 -03006580
Johan Hedberg744cf192011-11-08 20:40:14 +02006581int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006582 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006583 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006584{
6585 struct mgmt_ev_user_confirm_request ev;
6586
Johan Hedberg744cf192011-11-08 20:40:14 +02006587 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006588
Johan Hedberg272d90d2012-02-09 15:26:12 +02006589 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006590 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006591 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006592 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006593
Johan Hedberg744cf192011-11-08 20:40:14 +02006594 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006595 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006596}
6597
Johan Hedberg272d90d2012-02-09 15:26:12 +02006598int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006599 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006600{
6601 struct mgmt_ev_user_passkey_request ev;
6602
6603 BT_DBG("%s", hdev->name);
6604
Johan Hedberg272d90d2012-02-09 15:26:12 +02006605 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006606 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006607
6608 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006609 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006610}
6611
Brian Gix0df4c182011-11-16 13:53:13 -08006612static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006613 u8 link_type, u8 addr_type, u8 status,
6614 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006615{
6616 struct pending_cmd *cmd;
6617 struct mgmt_rp_user_confirm_reply rp;
6618 int err;
6619
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006620 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006621 if (!cmd)
6622 return -ENOENT;
6623
Johan Hedberg272d90d2012-02-09 15:26:12 +02006624 bacpy(&rp.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006625 rp.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergaee9b212012-02-18 15:07:59 +02006626 err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006627 &rp, sizeof(rp));
Johan Hedberga5c29682011-02-19 12:05:57 -03006628
Johan Hedberga664b5b2011-02-19 12:06:02 -03006629 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006630
6631 return err;
6632}
6633
Johan Hedberg744cf192011-11-08 20:40:14 +02006634int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006635 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006636{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006637 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006638 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006639}
6640
Johan Hedberg272d90d2012-02-09 15:26:12 +02006641int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006642 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006643{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006644 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006645 status,
6646 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006647}
Johan Hedberg2a611692011-02-19 12:06:00 -03006648
Brian Gix604086b2011-11-23 08:28:33 -08006649int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006650 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006651{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006652 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006653 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006654}
6655
Johan Hedberg272d90d2012-02-09 15:26:12 +02006656int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006657 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006658{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006659 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006660 status,
6661 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006662}
6663
Johan Hedberg92a25252012-09-06 18:39:26 +03006664int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6665 u8 link_type, u8 addr_type, u32 passkey,
6666 u8 entered)
6667{
6668 struct mgmt_ev_passkey_notify ev;
6669
6670 BT_DBG("%s", hdev->name);
6671
6672 bacpy(&ev.addr.bdaddr, bdaddr);
6673 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6674 ev.passkey = __cpu_to_le32(passkey);
6675 ev.entered = entered;
6676
6677 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6678}
6679
Johan Hedberge1e930f2014-09-08 17:09:49 -07006680void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006681{
6682 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006683 struct pending_cmd *cmd;
6684 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006685
Johan Hedberge1e930f2014-09-08 17:09:49 -07006686 bacpy(&ev.addr.bdaddr, &conn->dst);
6687 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6688 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006689
Johan Hedberge1e930f2014-09-08 17:09:49 -07006690 cmd = find_pairing(conn);
6691
6692 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6693 cmd ? cmd->sk : NULL);
6694
6695 if (cmd)
6696 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006697}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006698
Marcel Holtmann464996a2013-10-15 14:26:24 -07006699void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006700{
6701 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006702 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006703
6704 if (status) {
6705 u8 mgmt_err = mgmt_status(status);
6706 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006707 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006708 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006709 }
6710
Marcel Holtmann464996a2013-10-15 14:26:24 -07006711 if (test_bit(HCI_AUTH, &hdev->flags))
6712 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6713 &hdev->dev_flags);
6714 else
6715 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6716 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006717
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006718 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006719 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006720
Johan Hedberg47990ea2012-02-22 11:58:37 +02006721 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006722 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006723
6724 if (match.sk)
6725 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006726}
6727
Johan Hedberg890ea892013-03-15 17:06:52 -05006728static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006729{
Johan Hedberg890ea892013-03-15 17:06:52 -05006730 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006731 struct hci_cp_write_eir cp;
6732
Johan Hedberg976eb202012-10-24 21:12:01 +03006733 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006734 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006735
Johan Hedbergc80da272012-02-22 15:38:48 +02006736 memset(hdev->eir, 0, sizeof(hdev->eir));
6737
Johan Hedbergcacaf522012-02-21 00:52:42 +02006738 memset(&cp, 0, sizeof(cp));
6739
Johan Hedberg890ea892013-03-15 17:06:52 -05006740 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006741}
6742
Marcel Holtmann3e248562013-10-15 14:26:25 -07006743void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006744{
6745 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006746 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006747 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006748
6749 if (status) {
6750 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006751
6752 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006753 &hdev->dev_flags)) {
6754 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006755 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006756 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006757
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006758 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6759 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006760 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006761 }
6762
6763 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006764 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006765 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006766 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6767 if (!changed)
6768 changed = test_and_clear_bit(HCI_HS_ENABLED,
6769 &hdev->dev_flags);
6770 else
6771 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006772 }
6773
6774 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6775
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006776 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006777 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006778
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006779 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006780 sock_put(match.sk);
6781
Johan Hedberg890ea892013-03-15 17:06:52 -05006782 hci_req_init(&req, hdev);
6783
Johan Hedberg37699722014-06-24 14:00:27 +03006784 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6785 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6786 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6787 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006788 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006789 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006790 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006791 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006792
6793 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006794}
6795
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006796void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6797{
6798 struct cmd_lookup match = { NULL, hdev };
6799 bool changed = false;
6800
6801 if (status) {
6802 u8 mgmt_err = mgmt_status(status);
6803
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006804 if (enable) {
6805 if (test_and_clear_bit(HCI_SC_ENABLED,
6806 &hdev->dev_flags))
6807 new_settings(hdev, NULL);
6808 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6809 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006810
6811 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6812 cmd_status_rsp, &mgmt_err);
6813 return;
6814 }
6815
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006816 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006817 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006818 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006819 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006820 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6821 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006822
6823 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6824 settings_rsp, &match);
6825
6826 if (changed)
6827 new_settings(hdev, match.sk);
6828
6829 if (match.sk)
6830 sock_put(match.sk);
6831}
6832
Johan Hedberg92da6092013-03-15 17:06:55 -05006833static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006834{
6835 struct cmd_lookup *match = data;
6836
Johan Hedberg90e70452012-02-23 23:09:40 +02006837 if (match->sk == NULL) {
6838 match->sk = cmd->sk;
6839 sock_hold(match->sk);
6840 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006841}
6842
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006843void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6844 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006845{
Johan Hedberg90e70452012-02-23 23:09:40 +02006846 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006847
Johan Hedberg92da6092013-03-15 17:06:55 -05006848 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6849 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6850 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006851
6852 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006853 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6854 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006855
6856 if (match.sk)
6857 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006858}
6859
Marcel Holtmann7667da32013-10-15 14:26:27 -07006860void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006861{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006862 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006863 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006864
Johan Hedberg13928972013-03-15 17:07:00 -05006865 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006866 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006867
6868 memset(&ev, 0, sizeof(ev));
6869 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006870 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006871
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006872 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006873 if (!cmd) {
6874 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006875
Johan Hedberg13928972013-03-15 17:07:00 -05006876 /* If this is a HCI command related to powering on the
6877 * HCI dev don't send any mgmt signals.
6878 */
6879 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006880 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006881 }
6882
Marcel Holtmann7667da32013-10-15 14:26:27 -07006883 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6884 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006885}
Szymon Jancc35938b2011-03-22 13:12:21 +01006886
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006887void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006888 u8 *rand192, u8 *hash256, u8 *rand256,
6889 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006890{
6891 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006892
Johan Hedberg744cf192011-11-08 20:40:14 +02006893 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006894
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006895 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006896 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006897 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006898
6899 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006900 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6901 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006902 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006903 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006904 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006905
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006906 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006907 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006908
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006909 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006910 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006911
6912 cmd_complete(cmd->sk, hdev->id,
6913 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6914 &rp, sizeof(rp));
6915 } else {
6916 struct mgmt_rp_read_local_oob_data rp;
6917
6918 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006919 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006920
6921 cmd_complete(cmd->sk, hdev->id,
6922 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6923 &rp, sizeof(rp));
6924 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006925 }
6926
6927 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006928}
Johan Hedberge17acd42011-03-30 23:57:16 +03006929
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006930/* this is reversed hex representation of bluetooth base uuid. We need it for
6931 * service uuid parsing in eir.
6932 */
6933static const u8 reverse_base_uuid[] = {
6934 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6935 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6936};
6937
6938static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6939{
6940 int i;
6941
6942 for (i = 0; i < uuid_count; i++) {
6943 if (!memcmp(uuid, uuids[i], 16))
6944 return true;
6945 }
6946
6947 return false;
6948}
6949
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006950static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6951{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006952 u16 parsed = 0;
6953
6954 while (parsed < eir_len) {
6955 u8 field_len = eir[0];
6956 u8 uuid[16];
6957 int i;
6958
6959 if (field_len == 0)
6960 break;
6961
6962 if (eir_len - parsed < field_len + 1)
6963 break;
6964
6965 switch (eir[1]) {
6966 case EIR_UUID16_ALL:
6967 case EIR_UUID16_SOME:
6968 for (i = 0; i + 3 <= field_len; i += 2) {
6969 memcpy(uuid, reverse_base_uuid, 16);
6970 uuid[13] = eir[i + 3];
6971 uuid[12] = eir[i + 2];
6972 if (has_uuid(uuid, uuid_count, uuids))
6973 return true;
6974 }
6975 break;
6976 case EIR_UUID32_ALL:
6977 case EIR_UUID32_SOME:
6978 for (i = 0; i + 5 <= field_len; i += 4) {
6979 memcpy(uuid, reverse_base_uuid, 16);
6980 uuid[15] = eir[i + 5];
6981 uuid[14] = eir[i + 4];
6982 uuid[13] = eir[i + 3];
6983 uuid[12] = eir[i + 2];
6984 if (has_uuid(uuid, uuid_count, uuids))
6985 return true;
6986 }
6987 break;
6988 case EIR_UUID128_ALL:
6989 case EIR_UUID128_SOME:
6990 for (i = 0; i + 17 <= field_len; i += 16) {
6991 memcpy(uuid, eir + i + 2, 16);
6992 if (has_uuid(uuid, uuid_count, uuids))
6993 return true;
6994 }
6995 break;
6996 }
6997
6998 parsed += field_len + 1;
6999 eir += field_len + 1;
7000 }
7001
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007002 return false;
7003}
7004
Marcel Holtmann901801b2013-10-06 23:55:51 -07007005void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007006 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7007 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007008{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007009 char buf[512];
7010 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007011 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007012 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007013
Johan Hedberg75ce2082014-07-02 22:42:01 +03007014 /* Don't send events for a non-kernel initiated discovery. With
7015 * LE one exception is if we have pend_le_reports > 0 in which
7016 * case we're doing passive scanning and want these events.
7017 */
7018 if (!hci_discovery_active(hdev)) {
7019 if (link_type == ACL_LINK)
7020 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007021 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007022 return;
7023 }
Andre Guedes12602d02013-04-30 15:29:40 -03007024
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007025 /* When using service discovery with a RSSI threshold, then check
7026 * if such a RSSI threshold is specified. If a RSSI threshold has
7027 * been specified, then all results with a RSSI smaller than the
7028 * RSSI threshold will be dropped.
7029 */
7030 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7031 rssi < hdev->discovery.rssi)
7032 return;
7033
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007034 /* Make sure that the buffer is big enough. The 5 extra bytes
7035 * are for the potential CoD field.
7036 */
7037 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007038 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007039
Johan Hedberg1dc06092012-01-15 21:01:23 +02007040 memset(buf, 0, sizeof(buf));
7041
Johan Hedberg841c5642014-07-07 12:45:54 +03007042 bacpy(&ev->addr.bdaddr, bdaddr);
7043 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007044 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007045 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007046
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007047 if (eir_len > 0) {
7048 /* When using service discovery and a list of UUID is
7049 * provided, results with no matching UUID should be
7050 * dropped. In case there is a match the result is
7051 * kept and checking possible scan response data
7052 * will be skipped.
7053 */
7054 if (hdev->discovery.uuid_count > 0) {
7055 match = eir_has_uuids(eir, eir_len,
7056 hdev->discovery.uuid_count,
7057 hdev->discovery.uuids);
7058 if (!match)
7059 return;
7060 }
7061
7062 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007063 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007064 } else {
7065 /* When using service discovery and a list of UUID is
7066 * provided, results with empty EIR or advertising data
7067 * should be dropped since they do not match any UUID.
7068 */
7069 if (hdev->discovery.uuid_count > 0)
7070 return;
7071 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007072
Johan Hedberg1dc06092012-01-15 21:01:23 +02007073 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7074 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007075 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007076
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007077 if (scan_rsp_len > 0) {
7078 /* When using service discovery and a list of UUID is
7079 * provided, results with no matching UUID should be
7080 * dropped if there is no previous match from the
7081 * advertising data.
7082 */
7083 if (hdev->discovery.uuid_count > 0) {
7084 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7085 hdev->discovery.uuid_count,
7086 hdev->discovery.uuids))
7087 return;
7088 }
7089
7090 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007091 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007092 } else {
7093 /* When using service discovery and a list of UUID is
7094 * provided, results with empty scan response and no
7095 * previous matched advertising data should be dropped.
7096 */
7097 if (hdev->discovery.uuid_count > 0 && !match)
7098 return;
7099 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007100
7101 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7102 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007103
Marcel Holtmann901801b2013-10-06 23:55:51 -07007104 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007105}
Johan Hedberga88a9652011-03-30 13:18:12 +03007106
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007107void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7108 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007109{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007110 struct mgmt_ev_device_found *ev;
7111 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7112 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007113
Johan Hedbergb644ba32012-01-17 21:48:47 +02007114 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007115
Johan Hedbergb644ba32012-01-17 21:48:47 +02007116 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007117
Johan Hedbergb644ba32012-01-17 21:48:47 +02007118 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007119 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007120 ev->rssi = rssi;
7121
7122 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007123 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007124
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007125 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007126
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007127 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007128}
Johan Hedberg314b2382011-04-27 10:29:57 -04007129
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007130void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007131{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007132 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007133
Andre Guedes343fb142011-11-22 17:14:19 -03007134 BT_DBG("%s discovering %u", hdev->name, discovering);
7135
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007136 memset(&ev, 0, sizeof(ev));
7137 ev.type = hdev->discovery.type;
7138 ev.discovering = discovering;
7139
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007140 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007141}
Antti Julku5e762442011-08-25 16:48:02 +03007142
Marcel Holtmann5976e602013-10-06 04:08:14 -07007143static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7144{
7145 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007146}
7147
7148void mgmt_reenable_advertising(struct hci_dev *hdev)
7149{
7150 struct hci_request req;
7151
Marcel Holtmann5976e602013-10-06 04:08:14 -07007152 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7153 return;
7154
7155 hci_req_init(&req, hdev);
7156 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007157 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007158}