blob: d3ee7285c30385dab323f7979b0ad8d2ceded071 [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200138 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200141 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan 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 Hedberg84bde9d6c2012-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 Hedberg84bde9d6c2012-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 Hedberg7776d1d2014-12-05 13:36:03 +02001495static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1496{
1497 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
1499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001569 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001816 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001850 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
2202 if (status) {
2203 u8 mgmt_err = mgmt_status(status);
2204
2205 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2206 &mgmt_err);
2207 return;
2208 }
2209
2210 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2211
2212 new_settings(hdev, match.sk);
2213
2214 if (match.sk)
2215 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002216
2217 /* Make sure the controller has a good default for
2218 * advertising data. Restrict the update to when LE
2219 * has actually been enabled. During power on, the
2220 * update in powered_update_hci will take care of it.
2221 */
2222 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2223 struct hci_request req;
2224
2225 hci_dev_lock(hdev);
2226
2227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002230 hci_req_run(&req, NULL);
2231
Johan Hedberga70f4b52014-07-07 15:19:50 +03002232 hci_update_background_scan(hdev);
2233
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 hci_dev_unlock(hdev);
2235 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236}
2237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239{
2240 struct mgmt_mode *cp = data;
2241 struct hci_cp_write_le_host_supported hci_cp;
2242 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002245 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_le_capable(hdev))
2250 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_INVALID_PARAMS);
2256
Johan Hedbergc73eee92013-04-19 18:35:21 +03002257 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2260 MGMT_STATUS_REJECTED);
2261
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002262 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263
2264 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002265 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002267 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 bool changed = false;
2269
2270 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2271 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2272 changed = true;
2273 }
2274
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002275 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2276 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002277 changed = true;
2278 }
2279
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2281 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283
2284 if (changed)
2285 err = new_settings(hdev, sk);
2286
Johan Hedberg1de028c2012-02-29 19:55:35 -08002287 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288 }
2289
Johan Hedberg4375f102013-09-25 13:26:10 +03002290 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2291 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002300 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002303 hci_req_init(&req, hdev);
2304
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 memset(&hci_cp, 0, sizeof(hci_cp));
2306
2307 if (val) {
2308 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002309 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002310 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 }
2314
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002315 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2316 &hci_cp);
2317
2318 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302319 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322unlock:
2323 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 return err;
2325}
2326
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002327/* This is a helper function to test for pending mgmt commands that can
2328 * cause CoD or EIR HCI commands. We can only allow one such pending
2329 * mgmt command at a time since otherwise we cannot easily track what
2330 * the current values are, will be, and based on that calculate if a new
2331 * HCI command needs to be sent and if yes with what value.
2332 */
2333static bool pending_eir_or_class(struct hci_dev *hdev)
2334{
2335 struct pending_cmd *cmd;
2336
2337 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2338 switch (cmd->opcode) {
2339 case MGMT_OP_ADD_UUID:
2340 case MGMT_OP_REMOVE_UUID:
2341 case MGMT_OP_SET_DEV_CLASS:
2342 case MGMT_OP_SET_POWERED:
2343 return true;
2344 }
2345 }
2346
2347 return false;
2348}
2349
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002350static const u8 bluetooth_base_uuid[] = {
2351 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2352 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2353};
2354
2355static u8 get_uuid_size(const u8 *uuid)
2356{
2357 u32 val;
2358
2359 if (memcmp(uuid, bluetooth_base_uuid, 12))
2360 return 128;
2361
2362 val = get_unaligned_le32(&uuid[12]);
2363 if (val > 0xffff)
2364 return 32;
2365
2366 return 16;
2367}
2368
Johan Hedberg92da6092013-03-15 17:06:55 -05002369static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2370{
2371 struct pending_cmd *cmd;
2372
2373 hci_dev_lock(hdev);
2374
2375 cmd = mgmt_pending_find(mgmt_op, hdev);
2376 if (!cmd)
2377 goto unlock;
2378
2379 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2380 hdev->dev_class, 3);
2381
2382 mgmt_pending_remove(cmd);
2383
2384unlock:
2385 hci_dev_unlock(hdev);
2386}
2387
2388static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002397 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002398 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto failed;
2411 }
2412
Andre Guedes92c4c202012-06-07 19:05:44 -03002413 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002414 if (!uuid) {
2415 err = -ENOMEM;
2416 goto failed;
2417 }
2418
2419 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002421 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedbergde66aa62013-01-27 00:31:27 +02002423 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedberg890ea892013-03-15 17:06:52 -05002425 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 update_class(&req);
2428 update_eir(&req);
2429
Johan Hedberg92da6092013-03-15 17:06:55 -05002430 err = hci_req_run(&req, add_uuid_complete);
2431 if (err < 0) {
2432 if (err != -ENODATA)
2433 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002436 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002437 goto failed;
2438 }
2439
2440 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002442 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 goto failed;
2444 }
2445
2446 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447
2448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002449 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 return err;
2451}
2452
Johan Hedberg24b78d02012-02-23 23:24:30 +02002453static bool enable_service_cache(struct hci_dev *hdev)
2454{
2455 if (!hdev_is_powered(hdev))
2456 return false;
2457
2458 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002459 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2460 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002461 return true;
2462 }
2463
2464 return false;
2465}
2466
Johan Hedberg92da6092013-03-15 17:06:55 -05002467static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2468{
2469 BT_DBG("status 0x%02x", status);
2470
2471 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2472}
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002477 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002481 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 int err, found;
2483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002484 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002488 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002491 goto unlock;
2492 }
2493
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002494 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002495 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg24b78d02012-02-23 23:24:30 +02002497 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002500 goto unlock;
2501 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002502
Johan Hedberg9246a862012-02-23 21:33:16 +02002503 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504 }
2505
2506 found = 0;
2507
Johan Hedberg056341c2013-01-27 00:31:30 +02002508 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2510 continue;
2511
2512 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002513 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 found++;
2515 }
2516
2517 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002519 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 goto unlock;
2521 }
2522
Johan Hedberg9246a862012-02-23 21:33:16 +02002523update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527 update_eir(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, remove_uuid_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 return err;
2550}
2551
Johan Hedberg92da6092013-03-15 17:06:55 -05002552static void set_class_complete(struct hci_dev *hdev, u8 status)
2553{
2554 BT_DBG("status 0x%02x", status);
2555
2556 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002561{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002562 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002563 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002564 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565 int err;
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002569 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_NOT_SUPPORTED);
2572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002574
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002575 if (pending_eir_or_class(hdev)) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_BUSY);
2578 goto unlock;
2579 }
2580
2581 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2582 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2583 MGMT_STATUS_INVALID_PARAMS);
2584 goto unlock;
2585 }
2586
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002587 hdev->major_class = cp->major;
2588 hdev->minor_class = cp->minor;
2589
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002590 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002593 goto unlock;
2594 }
2595
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 hci_req_init(&req, hdev);
2597
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002598 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002599 hci_dev_unlock(hdev);
2600 cancel_delayed_work_sync(&hdev->service_cache);
2601 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002602 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606
Johan Hedberg92da6092013-03-15 17:06:55 -05002607 err = hci_req_run(&req, set_class_complete);
2608 if (err < 0) {
2609 if (err != -ENODATA)
2610 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002613 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 goto unlock;
2615 }
2616
2617 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002618 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002619 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 goto unlock;
2621 }
2622
2623 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624
Johan Hedbergb5235a62012-02-21 14:32:24 +02002625unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627 return err;
2628}
2629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002631 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002633 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002634 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2635 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002637 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002638 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002640 BT_DBG("request for %s", hdev->name);
2641
2642 if (!lmp_bredr_capable(hdev))
2643 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2644 MGMT_STATUS_NOT_SUPPORTED);
2645
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002646 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002647 if (key_count > max_key_count) {
2648 BT_ERR("load_link_keys: too big key_count value %u",
2649 key_count);
2650 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2651 MGMT_STATUS_INVALID_PARAMS);
2652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberg86742e12011-11-07 23:13:38 +02002654 expected_len = sizeof(*cp) + key_count *
2655 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002656 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002657 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002658 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedberg4ae14302013-01-20 14:27:13 +02002663 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2664 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2665 MGMT_STATUS_INVALID_PARAMS);
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002668 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 for (i = 0; i < key_count; i++) {
2671 struct mgmt_link_key_info *key = &cp->keys[i];
2672
Marcel Holtmann8e991132014-01-10 02:07:25 -08002673 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_INVALID_PARAMS);
2676 }
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
2680 hci_link_keys_clear(hdev);
2681
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2684 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2687 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002688
2689 if (changed)
2690 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002692 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002693 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg58e92932014-06-24 14:00:26 +03002695 /* Always ignore debug keys and require a new pairing if
2696 * the user wants to use them.
2697 */
2698 if (key->type == HCI_LK_DEBUG_COMBINATION)
2699 continue;
2700
Johan Hedberg7652ff62014-06-24 13:15:49 +03002701 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2702 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 }
2704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002709 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710}
2711
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714{
2715 struct mgmt_ev_device_unpaired ev;
2716
2717 bacpy(&ev.addr.bdaddr, bdaddr);
2718 ev.addr.type = addr_type;
2719
2720 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002722}
2723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 struct mgmt_cp_unpair_device *cp = data;
2728 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 struct hci_cp_disconnect dc;
2730 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 int err;
2733
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
2739 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
2742
Johan Hedberg118da702013-01-20 14:27:20 +02002743 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2744 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2745 MGMT_STATUS_INVALID_PARAMS,
2746 &rp, sizeof(rp));
2747
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002748 hci_dev_lock(hdev);
2749
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002750 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002751 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 goto unlock;
2754 }
2755
Johan Hedberge0b2b272014-02-18 17:14:31 +02002756 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002757 /* If disconnection is requested, then look up the
2758 * connection. If the remote device is connected, it
2759 * will be later used to terminate the link.
2760 *
2761 * Setting it to NULL explicitly will cause no
2762 * termination of the link.
2763 */
2764 if (cp->disconnect)
2765 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2766 &cp->addr.bdaddr);
2767 else
2768 conn = NULL;
2769
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 } else {
2772 u8 addr_type;
2773
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002774 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2775 &cp->addr.bdaddr);
2776 if (conn) {
2777 /* Defer clearing up the connection parameters
2778 * until closing to give a chance of keeping
2779 * them if a repairing happens.
2780 */
2781 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2782
2783 /* If disconnection is not requested, then
2784 * clear the connection variable so that the
2785 * link is not terminated.
2786 */
2787 if (!cp->disconnect)
2788 conn = NULL;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_LE_PUBLIC)
2792 addr_type = ADDR_LE_DEV_PUBLIC;
2793 else
2794 addr_type = ADDR_LE_DEV_RANDOM;
2795
Johan Hedberga7ec7332014-02-18 17:14:35 +02002796 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2797
Johan Hedberge0b2b272014-02-18 17:14:31 +02002798 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2799 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002802 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002803 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 goto unlock;
2805 }
2806
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002807 /* If the connection variable is set, then termination of the
2808 * link is requested.
2809 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002810 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002813 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 }
2816
Johan Hedberg124f6e32012-02-09 13:50:12 +02002817 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 if (!cmd) {
2820 err = -ENOMEM;
2821 goto unlock;
2822 }
2823
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002824 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002825 dc.reason = 0x13; /* Remote User Terminated Connection */
2826 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2827 if (err < 0)
2828 mgmt_pending_remove(cmd);
2829
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002830unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002831 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832 return err;
2833}
2834
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002835static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002836 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002837{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002838 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002839 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002840 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002841 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002842 int err;
2843
2844 BT_DBG("");
2845
Johan Hedberg06a63b12013-01-20 14:27:21 +02002846 memset(&rp, 0, sizeof(rp));
2847 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2848 rp.addr.type = cp->addr.type;
2849
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002850 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002851 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2852 MGMT_STATUS_INVALID_PARAMS,
2853 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002854
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002855 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002856
2857 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002858 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2859 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002860 goto failed;
2861 }
2862
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002863 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002864 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2865 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002866 goto failed;
2867 }
2868
Andre Guedes591f47f2012-04-24 21:02:49 -03002869 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002870 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2871 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002872 else
2873 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002874
Vishal Agarwalf9607272012-06-13 05:32:43 +05302875 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002876 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2877 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002878 goto failed;
2879 }
2880
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002881 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002882 if (!cmd) {
2883 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002884 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002885 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886
Johan Hedbergf5818c22014-12-05 13:36:02 +02002887 cmd->cmd_complete = generic_cmd_complete;
2888
Johan Hedberge3f2f922014-08-18 20:33:33 +03002889 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002890 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002891 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892
2893failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895 return err;
2896}
2897
Andre Guedes57c14772012-04-24 21:02:50 -03002898static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002899{
2900 switch (link_type) {
2901 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002902 switch (addr_type) {
2903 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002904 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002905
Johan Hedberg48264f02011-11-09 13:58:58 +02002906 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002907 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002908 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002909 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002910
Johan Hedberg4c659c32011-11-07 23:13:39 +02002911 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002912 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002913 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002914 }
2915}
2916
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002917static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2918 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002919{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002920 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002921 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002922 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002923 int err;
2924 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002925
2926 BT_DBG("");
2927
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002928 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002929
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002930 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002931 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002932 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002933 goto unlock;
2934 }
2935
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002936 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002937 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2938 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002939 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002940 }
2941
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002942 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002943 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002944 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002945 err = -ENOMEM;
2946 goto unlock;
2947 }
2948
Johan Hedberg2784eb42011-01-21 13:56:35 +02002949 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002950 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002951 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2952 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002954 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002955 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 continue;
2957 i++;
2958 }
2959
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002960 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002961
Johan Hedberg4c659c32011-11-07 23:13:39 +02002962 /* Recalculate length in case of filtered SCO connections, etc */
2963 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002964
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002965 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002966 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967
Johan Hedberga38528f2011-01-22 06:46:43 +02002968 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002969
2970unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002971 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002972 return err;
2973}
2974
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002975static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002976 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002977{
2978 struct pending_cmd *cmd;
2979 int err;
2980
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002981 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002983 if (!cmd)
2984 return -ENOMEM;
2985
Johan Hedbergd8457692012-02-17 14:24:57 +02002986 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002987 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002988 if (err < 0)
2989 mgmt_pending_remove(cmd);
2990
2991 return err;
2992}
2993
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002994static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002995 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002996{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002997 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002998 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02002999 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003000 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003001 int err;
3002
3003 BT_DBG("");
3004
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003005 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003006
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003007 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003008 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003009 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003010 goto failed;
3011 }
3012
Johan Hedbergd8457692012-02-17 14:24:57 +02003013 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003014 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003015 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003016 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017 goto failed;
3018 }
3019
3020 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003021 struct mgmt_cp_pin_code_neg_reply ncp;
3022
3023 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003024
3025 BT_ERR("PIN code is not 16 bytes long");
3026
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003027 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003028 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003030 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031
3032 goto failed;
3033 }
3034
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003035 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003036 if (!cmd) {
3037 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003038 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003039 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003041 cmd->cmd_complete = addr_cmd_complete;
3042
Johan Hedbergd8457692012-02-17 14:24:57 +02003043 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003044 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003045 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046
3047 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3048 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003049 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003050
3051failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003052 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053 return err;
3054}
3055
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003056static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3057 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003058{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003059 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060
3061 BT_DBG("");
3062
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003063 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3064 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3065 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3066
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003067 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003068
3069 hdev->io_capability = cp->io_capability;
3070
3071 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003072 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003073
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003074 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003076 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3077 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003078}
3079
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003080static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003081{
3082 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003083 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003085 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3087 continue;
3088
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089 if (cmd->user_data != conn)
3090 continue;
3091
3092 return cmd;
3093 }
3094
3095 return NULL;
3096}
3097
3098static void pairing_complete(struct pending_cmd *cmd, u8 status)
3099{
3100 struct mgmt_rp_pair_device rp;
3101 struct hci_conn *conn = cmd->user_data;
3102
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003103 bacpy(&rp.addr.bdaddr, &conn->dst);
3104 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003105
Johan Hedbergaee9b212012-02-18 15:07:59 +02003106 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003107 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003108
3109 /* So we don't get further callbacks for this connection */
3110 conn->connect_cfm_cb = NULL;
3111 conn->security_cfm_cb = NULL;
3112 conn->disconn_cfm_cb = NULL;
3113
David Herrmann76a68ba2013-04-06 20:28:37 +02003114 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003115 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003116
Johan Hedberga664b5b2011-02-19 12:06:02 -03003117 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003118
3119 /* The device is paired so there is no need to remove
3120 * its connection parameters anymore.
3121 */
3122 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003123}
3124
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003125void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3126{
3127 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3128 struct pending_cmd *cmd;
3129
3130 cmd = find_pairing(conn);
3131 if (cmd)
Johan Hedberg04ab2742014-12-05 13:36:04 +02003132 cmd->cmd_complete(cmd, status);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003133}
3134
Johan Hedberge9a416b2011-02-19 12:05:56 -03003135static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3136{
3137 struct pending_cmd *cmd;
3138
3139 BT_DBG("status %u", status);
3140
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003141 cmd = find_pairing(conn);
3142 if (!cmd)
3143 BT_DBG("Unable to find a pending command");
3144 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003145 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003146}
3147
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003148static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303149{
3150 struct pending_cmd *cmd;
3151
3152 BT_DBG("status %u", status);
3153
3154 if (!status)
3155 return;
3156
3157 cmd = find_pairing(conn);
3158 if (!cmd)
3159 BT_DBG("Unable to find a pending command");
3160 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003161 cmd->cmd_complete(cmd, mgmt_status(status));
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303162}
3163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003164static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003165 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003167 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003168 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169 struct pending_cmd *cmd;
3170 u8 sec_level, auth_type;
3171 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003172 int err;
3173
3174 BT_DBG("");
3175
Szymon Jancf950a30e2013-01-18 12:48:07 +01003176 memset(&rp, 0, sizeof(rp));
3177 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3178 rp.addr.type = cp->addr.type;
3179
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003180 if (!bdaddr_type_is_valid(cp->addr.type))
3181 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3182 MGMT_STATUS_INVALID_PARAMS,
3183 &rp, sizeof(rp));
3184
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003185 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3186 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3187 MGMT_STATUS_INVALID_PARAMS,
3188 &rp, sizeof(rp));
3189
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003190 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003191
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003192 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003193 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3194 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003195 goto unlock;
3196 }
3197
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003198 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003199 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003200
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003201 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003202 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3203 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003204 } else {
3205 u8 addr_type;
3206
3207 /* Convert from L2CAP channel address type to HCI address type
3208 */
3209 if (cp->addr.type == BDADDR_LE_PUBLIC)
3210 addr_type = ADDR_LE_DEV_PUBLIC;
3211 else
3212 addr_type = ADDR_LE_DEV_RANDOM;
3213
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003214 /* When pairing a new device, it is expected to remember
3215 * this device for future connections. Adding the connection
3216 * parameter information ahead of time allows tracking
3217 * of the slave preferred values and will speed up any
3218 * further connection establishment.
3219 *
3220 * If connection parameters already exist, then they
3221 * will be kept and this function does nothing.
3222 */
3223 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3224
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003225 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003226 sec_level, HCI_LE_CONN_TIMEOUT,
3227 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003228 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003229
Ville Tervo30e76272011-02-22 16:10:53 -03003230 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003231 int status;
3232
3233 if (PTR_ERR(conn) == -EBUSY)
3234 status = MGMT_STATUS_BUSY;
3235 else
3236 status = MGMT_STATUS_CONNECT_FAILED;
3237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003238 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003239 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003240 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003241 goto unlock;
3242 }
3243
3244 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003245 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003246 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003247 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003248 goto unlock;
3249 }
3250
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003251 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003252 if (!cmd) {
3253 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003254 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003255 goto unlock;
3256 }
3257
Johan Hedberg04ab2742014-12-05 13:36:04 +02003258 cmd->cmd_complete = pairing_complete;
3259
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003260 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003261 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003262 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003263 conn->security_cfm_cb = pairing_complete_cb;
3264 conn->disconn_cfm_cb = pairing_complete_cb;
3265 } else {
3266 conn->connect_cfm_cb = le_pairing_complete_cb;
3267 conn->security_cfm_cb = le_pairing_complete_cb;
3268 conn->disconn_cfm_cb = le_pairing_complete_cb;
3269 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003270
Johan Hedberge9a416b2011-02-19 12:05:56 -03003271 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003272 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003273
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003274 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003275 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003276 pairing_complete(cmd, 0);
3277
3278 err = 0;
3279
3280unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003281 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282 return err;
3283}
3284
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003285static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3286 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003287{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003288 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003289 struct pending_cmd *cmd;
3290 struct hci_conn *conn;
3291 int err;
3292
3293 BT_DBG("");
3294
Johan Hedberg28424702012-02-02 04:02:29 +02003295 hci_dev_lock(hdev);
3296
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003297 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003298 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003299 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003300 goto unlock;
3301 }
3302
Johan Hedberg28424702012-02-02 04:02:29 +02003303 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3304 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003305 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003306 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003307 goto unlock;
3308 }
3309
3310 conn = cmd->user_data;
3311
3312 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003313 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003314 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003315 goto unlock;
3316 }
3317
3318 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3319
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003320 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003321 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003322unlock:
3323 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003324 return err;
3325}
3326
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003327static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003328 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003329 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003330{
Johan Hedberga5c29682011-02-19 12:05:57 -03003331 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003332 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003333 int err;
3334
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003335 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003336
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003337 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003338 err = cmd_complete(sk, hdev->id, mgmt_op,
3339 MGMT_STATUS_NOT_POWERED, addr,
3340 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003341 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003342 }
3343
Johan Hedberg1707c602013-03-15 17:07:15 -05003344 if (addr->type == BDADDR_BREDR)
3345 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003346 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003347 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003348
Johan Hedberg272d90d2012-02-09 15:26:12 +02003349 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003350 err = cmd_complete(sk, hdev->id, mgmt_op,
3351 MGMT_STATUS_NOT_CONNECTED, addr,
3352 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003353 goto done;
3354 }
3355
Johan Hedberg1707c602013-03-15 17:07:15 -05003356 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003357 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003358 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003359 err = cmd_complete(sk, hdev->id, mgmt_op,
3360 MGMT_STATUS_SUCCESS, addr,
3361 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003362 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003363 err = cmd_complete(sk, hdev->id, mgmt_op,
3364 MGMT_STATUS_FAILED, addr,
3365 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003366
Brian Gix47c15e22011-11-16 13:53:14 -08003367 goto done;
3368 }
3369
Johan Hedberg1707c602013-03-15 17:07:15 -05003370 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003371 if (!cmd) {
3372 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003373 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003374 }
3375
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003376 cmd->cmd_complete = addr_cmd_complete;
3377
Brian Gix0df4c182011-11-16 13:53:13 -08003378 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003379 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3380 struct hci_cp_user_passkey_reply cp;
3381
Johan Hedberg1707c602013-03-15 17:07:15 -05003382 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003383 cp.passkey = passkey;
3384 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3385 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003386 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3387 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003388
Johan Hedberga664b5b2011-02-19 12:06:02 -03003389 if (err < 0)
3390 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003391
Brian Gix0df4c182011-11-16 13:53:13 -08003392done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003393 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003394 return err;
3395}
3396
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303397static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3398 void *data, u16 len)
3399{
3400 struct mgmt_cp_pin_code_neg_reply *cp = data;
3401
3402 BT_DBG("");
3403
Johan Hedberg1707c602013-03-15 17:07:15 -05003404 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303405 MGMT_OP_PIN_CODE_NEG_REPLY,
3406 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3407}
3408
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003409static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3410 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003411{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003412 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003413
3414 BT_DBG("");
3415
3416 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003417 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003418 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003419
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_REPLY,
3422 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003423}
3424
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003425static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003426 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003427{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003428 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -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_CONFIRM_NEG_REPLY,
3434 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003435}
3436
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003437static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3438 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003439{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003440 struct mgmt_cp_user_passkey_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_REPLY,
3446 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003447}
3448
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003449static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003450 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003451{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003452 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003453
3454 BT_DBG("");
3455
Johan Hedberg1707c602013-03-15 17:07:15 -05003456 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003457 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3458 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003459}
3460
Johan Hedberg13928972013-03-15 17:07:00 -05003461static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003462{
Johan Hedberg13928972013-03-15 17:07:00 -05003463 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003464 struct hci_cp_write_local_name cp;
3465
Johan Hedberg13928972013-03-15 17:07:00 -05003466 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003467
Johan Hedberg890ea892013-03-15 17:06:52 -05003468 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003469}
3470
Johan Hedberg13928972013-03-15 17:07:00 -05003471static void set_name_complete(struct hci_dev *hdev, u8 status)
3472{
3473 struct mgmt_cp_set_local_name *cp;
3474 struct pending_cmd *cmd;
3475
3476 BT_DBG("status 0x%02x", status);
3477
3478 hci_dev_lock(hdev);
3479
3480 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3481 if (!cmd)
3482 goto unlock;
3483
3484 cp = cmd->param;
3485
3486 if (status)
3487 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3488 mgmt_status(status));
3489 else
3490 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3491 cp, sizeof(*cp));
3492
3493 mgmt_pending_remove(cmd);
3494
3495unlock:
3496 hci_dev_unlock(hdev);
3497}
3498
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003499static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003501{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003502 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003503 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003504 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003505 int err;
3506
3507 BT_DBG("");
3508
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003509 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003510
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003511 /* If the old values are the same as the new ones just return a
3512 * direct command complete event.
3513 */
3514 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3515 !memcmp(hdev->short_name, cp->short_name,
3516 sizeof(hdev->short_name))) {
3517 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3518 data, len);
3519 goto failed;
3520 }
3521
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003522 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003523
Johan Hedbergb5235a62012-02-21 14:32:24 +02003524 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003525 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003526
3527 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003528 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003529 if (err < 0)
3530 goto failed;
3531
3532 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003533 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003534
Johan Hedbergb5235a62012-02-21 14:32:24 +02003535 goto failed;
3536 }
3537
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003538 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003539 if (!cmd) {
3540 err = -ENOMEM;
3541 goto failed;
3542 }
3543
Johan Hedberg13928972013-03-15 17:07:00 -05003544 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3545
Johan Hedberg890ea892013-03-15 17:06:52 -05003546 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003547
3548 if (lmp_bredr_capable(hdev)) {
3549 update_name(&req);
3550 update_eir(&req);
3551 }
3552
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003553 /* The name is stored in the scan response data and so
3554 * no need to udpate the advertising data here.
3555 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003556 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003557 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003558
Johan Hedberg13928972013-03-15 17:07:00 -05003559 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003560 if (err < 0)
3561 mgmt_pending_remove(cmd);
3562
3563failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003564 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003565 return err;
3566}
3567
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003568static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003569 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003570{
Szymon Jancc35938b2011-03-22 13:12:21 +01003571 struct pending_cmd *cmd;
3572 int err;
3573
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003574 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003575
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003576 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003577
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003578 if (!hdev_is_powered(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_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003581 goto unlock;
3582 }
3583
Andre Guedes9a1a1992012-07-24 15:03:48 -03003584 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003585 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003586 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003587 goto unlock;
3588 }
3589
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003590 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003591 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003592 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003593 goto unlock;
3594 }
3595
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003596 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003597 if (!cmd) {
3598 err = -ENOMEM;
3599 goto unlock;
3600 }
3601
Johan Hedberg710f11c2014-05-26 11:21:22 +03003602 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003603 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3604 0, NULL);
3605 else
3606 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3607
Szymon Jancc35938b2011-03-22 13:12:21 +01003608 if (err < 0)
3609 mgmt_pending_remove(cmd);
3610
3611unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003612 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003613 return err;
3614}
3615
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003616static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003617 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003618{
Szymon Janc2763eda2011-03-22 13:12:22 +01003619 int err;
3620
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003621 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003622
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003623 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003624
Marcel Holtmannec109112014-01-10 02:07:30 -08003625 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3626 struct mgmt_cp_add_remote_oob_data *cp = data;
3627 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003628
Johan Hedbergc19a4952014-11-17 20:52:19 +02003629 if (cp->addr.type != BDADDR_BREDR) {
3630 err = cmd_complete(sk, hdev->id,
3631 MGMT_OP_ADD_REMOTE_OOB_DATA,
3632 MGMT_STATUS_INVALID_PARAMS,
3633 &cp->addr, sizeof(cp->addr));
3634 goto unlock;
3635 }
3636
Marcel Holtmannec109112014-01-10 02:07:30 -08003637 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003638 cp->addr.type, cp->hash,
3639 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003640 if (err < 0)
3641 status = MGMT_STATUS_FAILED;
3642 else
3643 status = MGMT_STATUS_SUCCESS;
3644
3645 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3646 status, &cp->addr, sizeof(cp->addr));
3647 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3648 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003649 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003650 u8 status;
3651
Johan Hedbergc19a4952014-11-17 20:52:19 +02003652 if (cp->addr.type != BDADDR_BREDR) {
3653 err = cmd_complete(sk, hdev->id,
3654 MGMT_OP_ADD_REMOTE_OOB_DATA,
3655 MGMT_STATUS_INVALID_PARAMS,
3656 &cp->addr, sizeof(cp->addr));
3657 goto unlock;
3658 }
3659
Johan Hedberg86df9202014-10-26 20:52:27 +01003660 if (bdaddr_type_is_le(cp->addr.type)) {
3661 rand192 = NULL;
3662 hash192 = NULL;
3663 } else {
3664 rand192 = cp->rand192;
3665 hash192 = cp->hash192;
3666 }
3667
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003668 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003669 cp->addr.type, hash192, rand192,
3670 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003671 if (err < 0)
3672 status = MGMT_STATUS_FAILED;
3673 else
3674 status = MGMT_STATUS_SUCCESS;
3675
3676 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3677 status, &cp->addr, sizeof(cp->addr));
3678 } else {
3679 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3680 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3681 MGMT_STATUS_INVALID_PARAMS);
3682 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003683
Johan Hedbergc19a4952014-11-17 20:52:19 +02003684unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003685 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003686 return err;
3687}
3688
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003689static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003690 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003691{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003692 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003693 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003694 int err;
3695
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003696 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003697
Johan Hedbergc19a4952014-11-17 20:52:19 +02003698 if (cp->addr.type != BDADDR_BREDR)
3699 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3700 MGMT_STATUS_INVALID_PARAMS,
3701 &cp->addr, sizeof(cp->addr));
3702
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003703 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003704
Johan Hedbergeedbd582014-11-15 09:34:23 +02003705 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3706 hci_remote_oob_data_clear(hdev);
3707 status = MGMT_STATUS_SUCCESS;
3708 goto done;
3709 }
3710
Johan Hedberg6928a922014-10-26 20:46:09 +01003711 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003712 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003713 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003714 else
Szymon Janca6785be2012-12-13 15:11:21 +01003715 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003716
Johan Hedbergeedbd582014-11-15 09:34:23 +02003717done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003718 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003719 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003720
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003721 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003722 return err;
3723}
3724
Marcel Holtmann80190442014-12-04 11:36:36 +01003725static bool trigger_discovery(struct hci_request *req, u8 *status)
3726{
3727 struct hci_dev *hdev = req->hdev;
3728 struct hci_cp_le_set_scan_param param_cp;
3729 struct hci_cp_le_set_scan_enable enable_cp;
3730 struct hci_cp_inquiry inq_cp;
3731 /* General inquiry access code (GIAC) */
3732 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3733 u8 own_addr_type;
3734 int err;
3735
3736 switch (hdev->discovery.type) {
3737 case DISCOV_TYPE_BREDR:
3738 *status = mgmt_bredr_support(hdev);
3739 if (*status)
3740 return false;
3741
3742 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3743 *status = MGMT_STATUS_BUSY;
3744 return false;
3745 }
3746
3747 hci_inquiry_cache_flush(hdev);
3748
3749 memset(&inq_cp, 0, sizeof(inq_cp));
3750 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3751 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3752 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3753 break;
3754
3755 case DISCOV_TYPE_LE:
3756 case DISCOV_TYPE_INTERLEAVED:
3757 *status = mgmt_le_support(hdev);
3758 if (*status)
3759 return false;
3760
3761 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3762 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3763 *status = MGMT_STATUS_NOT_SUPPORTED;
3764 return false;
3765 }
3766
3767 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3768 /* Don't let discovery abort an outgoing
3769 * connection attempt that's using directed
3770 * advertising.
3771 */
3772 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3773 BT_CONNECT)) {
3774 *status = MGMT_STATUS_REJECTED;
3775 return false;
3776 }
3777
3778 disable_advertising(req);
3779 }
3780
3781 /* If controller is scanning, it means the background scanning
3782 * is running. Thus, we should temporarily stop it in order to
3783 * set the discovery scanning parameters.
3784 */
3785 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3786 hci_req_add_le_scan_disable(req);
3787
3788 memset(&param_cp, 0, sizeof(param_cp));
3789
3790 /* All active scans will be done with either a resolvable
3791 * private address (when privacy feature has been enabled)
3792 * or unresolvable private address.
3793 */
3794 err = hci_update_random_address(req, true, &own_addr_type);
3795 if (err < 0) {
3796 *status = MGMT_STATUS_FAILED;
3797 return false;
3798 }
3799
3800 param_cp.type = LE_SCAN_ACTIVE;
3801 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3802 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3803 param_cp.own_address_type = own_addr_type;
3804 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3805 &param_cp);
3806
3807 memset(&enable_cp, 0, sizeof(enable_cp));
3808 enable_cp.enable = LE_SCAN_ENABLE;
3809 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3810 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3811 &enable_cp);
3812 break;
3813
3814 default:
3815 *status = MGMT_STATUS_INVALID_PARAMS;
3816 return false;
3817 }
3818
3819 return true;
3820}
3821
Andre Guedes7c307722013-04-30 15:29:28 -03003822static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3823{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003824 struct pending_cmd *cmd;
3825 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003826
Andre Guedes7c307722013-04-30 15:29:28 -03003827 BT_DBG("status %d", status);
3828
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003829 hci_dev_lock(hdev);
3830
3831 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003832 if (!cmd)
3833 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3834
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003835 if (cmd) {
3836 u8 type = hdev->discovery.type;
3837
3838 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
3839 mgmt_status(status), &type, sizeof(type));
3840 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003841 }
3842
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003843 if (status) {
3844 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3845 goto unlock;
3846 }
3847
Andre Guedes7c307722013-04-30 15:29:28 -03003848 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003849
3850 switch (hdev->discovery.type) {
3851 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003852 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003853 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003854 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003855 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003856 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003857 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003858 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003859 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003860 default:
3861 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003862 timeout = 0;
3863 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003864 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003865
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003866 if (timeout)
3867 queue_delayed_work(hdev->workqueue,
3868 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003869
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003870unlock:
3871 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003872}
3873
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003874static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003875 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003876{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003877 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003878 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003879 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003880 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003881 int err;
3882
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003883 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003884
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003885 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003886
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003887 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003888 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3889 MGMT_STATUS_NOT_POWERED,
3890 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003891 goto failed;
3892 }
3893
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003894 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3895 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003896 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3897 MGMT_STATUS_BUSY, &cp->type,
3898 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003899 goto failed;
3900 }
3901
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003902 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04003903 if (!cmd) {
3904 err = -ENOMEM;
3905 goto failed;
3906 }
3907
Marcel Holtmann22078802014-12-05 11:45:22 +01003908 /* Clear the discovery filter first to free any previously
3909 * allocated memory for the UUID list.
3910 */
3911 hci_discovery_filter_clear(hdev);
3912
Andre Guedes4aab14e2012-02-17 20:39:36 -03003913 hdev->discovery.type = cp->type;
3914
Andre Guedes7c307722013-04-30 15:29:28 -03003915 hci_req_init(&req, hdev);
3916
Marcel Holtmann80190442014-12-04 11:36:36 +01003917 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003918 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003919 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003920 mgmt_pending_remove(cmd);
3921 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003922 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003923
Andre Guedes7c307722013-04-30 15:29:28 -03003924 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003925 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003926 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003927 goto failed;
3928 }
3929
3930 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003931
3932failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003933 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003934 return err;
3935}
3936
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003937static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3938 void *data, u16 len)
3939{
3940 struct mgmt_cp_start_service_discovery *cp = data;
3941 struct pending_cmd *cmd;
3942 struct hci_request req;
3943 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3944 u16 uuid_count, expected_len;
3945 u8 status;
3946 int err;
3947
3948 BT_DBG("%s", hdev->name);
3949
3950 hci_dev_lock(hdev);
3951
3952 if (!hdev_is_powered(hdev)) {
3953 err = cmd_complete(sk, hdev->id,
3954 MGMT_OP_START_SERVICE_DISCOVERY,
3955 MGMT_STATUS_NOT_POWERED,
3956 &cp->type, sizeof(cp->type));
3957 goto failed;
3958 }
3959
3960 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3961 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3962 err = cmd_complete(sk, hdev->id,
3963 MGMT_OP_START_SERVICE_DISCOVERY,
3964 MGMT_STATUS_BUSY, &cp->type,
3965 sizeof(cp->type));
3966 goto failed;
3967 }
3968
3969 uuid_count = __le16_to_cpu(cp->uuid_count);
3970 if (uuid_count > max_uuid_count) {
3971 BT_ERR("service_discovery: too big uuid_count value %u",
3972 uuid_count);
3973 err = cmd_complete(sk, hdev->id,
3974 MGMT_OP_START_SERVICE_DISCOVERY,
3975 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3976 sizeof(cp->type));
3977 goto failed;
3978 }
3979
3980 expected_len = sizeof(*cp) + uuid_count * 16;
3981 if (expected_len != len) {
3982 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3983 expected_len, len);
3984 err = cmd_complete(sk, hdev->id,
3985 MGMT_OP_START_SERVICE_DISCOVERY,
3986 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3987 sizeof(cp->type));
3988 goto failed;
3989 }
3990
3991 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
3992 hdev, NULL, 0);
3993 if (!cmd) {
3994 err = -ENOMEM;
3995 goto failed;
3996 }
3997
Marcel Holtmann22078802014-12-05 11:45:22 +01003998 /* Clear the discovery filter first to free any previously
3999 * allocated memory for the UUID list.
4000 */
4001 hci_discovery_filter_clear(hdev);
4002
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004003 hdev->discovery.type = cp->type;
4004 hdev->discovery.rssi = cp->rssi;
4005 hdev->discovery.uuid_count = uuid_count;
4006
4007 if (uuid_count > 0) {
4008 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4009 GFP_KERNEL);
4010 if (!hdev->discovery.uuids) {
4011 err = cmd_complete(sk, hdev->id,
4012 MGMT_OP_START_SERVICE_DISCOVERY,
4013 MGMT_STATUS_FAILED,
4014 &cp->type, sizeof(cp->type));
4015 mgmt_pending_remove(cmd);
4016 goto failed;
4017 }
4018 }
4019
4020 hci_req_init(&req, hdev);
4021
4022 if (!trigger_discovery(&req, &status)) {
4023 err = cmd_complete(sk, hdev->id,
4024 MGMT_OP_START_SERVICE_DISCOVERY,
4025 status, &cp->type, sizeof(cp->type));
4026 mgmt_pending_remove(cmd);
4027 goto failed;
4028 }
4029
4030 err = hci_req_run(&req, start_discovery_complete);
4031 if (err < 0) {
4032 mgmt_pending_remove(cmd);
4033 goto failed;
4034 }
4035
4036 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4037
4038failed:
4039 hci_dev_unlock(hdev);
4040 return err;
4041}
4042
Andre Guedes0e05bba2013-04-30 15:29:33 -03004043static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4044{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004045 struct pending_cmd *cmd;
4046
Andre Guedes0e05bba2013-04-30 15:29:33 -03004047 BT_DBG("status %d", status);
4048
4049 hci_dev_lock(hdev);
4050
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004051 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4052 if (cmd) {
4053 u8 type = hdev->discovery.type;
4054
4055 cmd_complete(cmd->sk, hdev->id, cmd->opcode,
4056 mgmt_status(status), &type, sizeof(type));
4057 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004058 }
4059
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004060 if (!status)
4061 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004062
Andre Guedes0e05bba2013-04-30 15:29:33 -03004063 hci_dev_unlock(hdev);
4064}
4065
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004066static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004067 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004068{
Johan Hedbergd9306502012-02-20 23:25:18 +02004069 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004070 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004071 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004072 int err;
4073
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004074 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004075
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004076 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004077
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004078 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004079 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004080 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4081 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004082 goto unlock;
4083 }
4084
4085 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004086 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004087 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4088 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004089 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004090 }
4091
Johan Hedberg2e58ef32011-11-08 20:40:15 +02004092 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
Johan Hedberg14a53662011-04-27 10:29:56 -04004093 if (!cmd) {
4094 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004095 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004096 }
4097
Andre Guedes0e05bba2013-04-30 15:29:33 -03004098 hci_req_init(&req, hdev);
4099
Johan Hedberg21a60d32014-06-10 14:05:58 +03004100 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004101
Johan Hedberg21a60d32014-06-10 14:05:58 +03004102 err = hci_req_run(&req, stop_discovery_complete);
4103 if (!err) {
4104 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004105 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004106 }
4107
Johan Hedberg21a60d32014-06-10 14:05:58 +03004108 mgmt_pending_remove(cmd);
4109
4110 /* If no HCI commands were sent we're done */
4111 if (err == -ENODATA) {
4112 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4113 &mgmt_cp->type, sizeof(mgmt_cp->type));
4114 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4115 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004116
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004117unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004118 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004119 return err;
4120}
4121
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004122static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004123 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004124{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004125 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004126 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004127 int err;
4128
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004129 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004130
Johan Hedberg561aafb2012-01-04 13:31:59 +02004131 hci_dev_lock(hdev);
4132
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004133 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004134 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4135 MGMT_STATUS_FAILED, &cp->addr,
4136 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004137 goto failed;
4138 }
4139
Johan Hedberga198e7b2012-02-17 14:27:06 +02004140 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004141 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004142 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4143 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4144 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004145 goto failed;
4146 }
4147
4148 if (cp->name_known) {
4149 e->name_state = NAME_KNOWN;
4150 list_del(&e->list);
4151 } else {
4152 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004153 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004154 }
4155
Johan Hedberge3846622013-01-09 15:29:33 +02004156 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4157 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004158
4159failed:
4160 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004161 return err;
4162}
4163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004164static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004165 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004166{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004167 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004168 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004169 int err;
4170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004171 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004172
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004173 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004174 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4175 MGMT_STATUS_INVALID_PARAMS,
4176 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004177
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004178 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004179
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004180 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4181 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004182 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004183 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004184 goto done;
4185 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004186
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004187 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4188 sk);
4189 status = MGMT_STATUS_SUCCESS;
4190
4191done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004192 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004193 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004194
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004195 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004196
4197 return err;
4198}
4199
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004200static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004201 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004202{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004203 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004204 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004205 int err;
4206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004207 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004208
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004209 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004210 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4211 MGMT_STATUS_INVALID_PARAMS,
4212 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004213
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004214 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004215
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004216 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4217 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004218 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004219 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004220 goto done;
4221 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004222
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004223 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4224 sk);
4225 status = MGMT_STATUS_SUCCESS;
4226
4227done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004228 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004229 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004230
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004231 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004232
4233 return err;
4234}
4235
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004236static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4237 u16 len)
4238{
4239 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004240 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004241 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004242 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004243
4244 BT_DBG("%s", hdev->name);
4245
Szymon Jancc72d4b82012-03-16 16:02:57 +01004246 source = __le16_to_cpu(cp->source);
4247
4248 if (source > 0x0002)
4249 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4250 MGMT_STATUS_INVALID_PARAMS);
4251
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004252 hci_dev_lock(hdev);
4253
Szymon Jancc72d4b82012-03-16 16:02:57 +01004254 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004255 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4256 hdev->devid_product = __le16_to_cpu(cp->product);
4257 hdev->devid_version = __le16_to_cpu(cp->version);
4258
4259 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4260
Johan Hedberg890ea892013-03-15 17:06:52 -05004261 hci_req_init(&req, hdev);
4262 update_eir(&req);
4263 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004264
4265 hci_dev_unlock(hdev);
4266
4267 return err;
4268}
4269
Johan Hedberg4375f102013-09-25 13:26:10 +03004270static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4271{
4272 struct cmd_lookup match = { NULL, hdev };
4273
4274 if (status) {
4275 u8 mgmt_err = mgmt_status(status);
4276
4277 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4278 cmd_status_rsp, &mgmt_err);
4279 return;
4280 }
4281
Johan Hedbergc93bd152014-07-08 15:07:48 +03004282 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4283 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4284 else
4285 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4286
Johan Hedberg4375f102013-09-25 13:26:10 +03004287 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4288 &match);
4289
4290 new_settings(hdev, match.sk);
4291
4292 if (match.sk)
4293 sock_put(match.sk);
4294}
4295
Marcel Holtmann21b51872013-10-10 09:47:53 -07004296static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4297 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004298{
4299 struct mgmt_mode *cp = data;
4300 struct pending_cmd *cmd;
4301 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004302 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004303 int err;
4304
4305 BT_DBG("request for %s", hdev->name);
4306
Johan Hedberge6fe7982013-10-02 15:45:22 +03004307 status = mgmt_le_support(hdev);
4308 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004309 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004310 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004311
4312 if (cp->val != 0x00 && cp->val != 0x01)
4313 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4314 MGMT_STATUS_INVALID_PARAMS);
4315
4316 hci_dev_lock(hdev);
4317
4318 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004319 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004320
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004321 /* The following conditions are ones which mean that we should
4322 * not do any HCI communication but directly send a mgmt
4323 * response to user space (after toggling the flag if
4324 * necessary).
4325 */
4326 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004327 hci_conn_num(hdev, LE_LINK) > 0 ||
4328 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4329 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004330 bool changed = false;
4331
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004332 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4333 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004334 changed = true;
4335 }
4336
4337 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4338 if (err < 0)
4339 goto unlock;
4340
4341 if (changed)
4342 err = new_settings(hdev, sk);
4343
4344 goto unlock;
4345 }
4346
4347 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4348 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4349 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4350 MGMT_STATUS_BUSY);
4351 goto unlock;
4352 }
4353
4354 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4355 if (!cmd) {
4356 err = -ENOMEM;
4357 goto unlock;
4358 }
4359
4360 hci_req_init(&req, hdev);
4361
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004362 if (val)
4363 enable_advertising(&req);
4364 else
4365 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004366
4367 err = hci_req_run(&req, set_advertising_complete);
4368 if (err < 0)
4369 mgmt_pending_remove(cmd);
4370
4371unlock:
4372 hci_dev_unlock(hdev);
4373 return err;
4374}
4375
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004376static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4377 void *data, u16 len)
4378{
4379 struct mgmt_cp_set_static_address *cp = data;
4380 int err;
4381
4382 BT_DBG("%s", hdev->name);
4383
Marcel Holtmann62af4442013-10-02 22:10:32 -07004384 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004385 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004386 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004387
4388 if (hdev_is_powered(hdev))
4389 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4390 MGMT_STATUS_REJECTED);
4391
4392 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4393 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4394 return cmd_status(sk, hdev->id,
4395 MGMT_OP_SET_STATIC_ADDRESS,
4396 MGMT_STATUS_INVALID_PARAMS);
4397
4398 /* Two most significant bits shall be set */
4399 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4400 return cmd_status(sk, hdev->id,
4401 MGMT_OP_SET_STATIC_ADDRESS,
4402 MGMT_STATUS_INVALID_PARAMS);
4403 }
4404
4405 hci_dev_lock(hdev);
4406
4407 bacpy(&hdev->static_addr, &cp->bdaddr);
4408
4409 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4410
4411 hci_dev_unlock(hdev);
4412
4413 return err;
4414}
4415
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004416static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4417 void *data, u16 len)
4418{
4419 struct mgmt_cp_set_scan_params *cp = data;
4420 __u16 interval, window;
4421 int err;
4422
4423 BT_DBG("%s", hdev->name);
4424
4425 if (!lmp_le_capable(hdev))
4426 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4427 MGMT_STATUS_NOT_SUPPORTED);
4428
4429 interval = __le16_to_cpu(cp->interval);
4430
4431 if (interval < 0x0004 || interval > 0x4000)
4432 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4433 MGMT_STATUS_INVALID_PARAMS);
4434
4435 window = __le16_to_cpu(cp->window);
4436
4437 if (window < 0x0004 || window > 0x4000)
4438 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4439 MGMT_STATUS_INVALID_PARAMS);
4440
Marcel Holtmann899e1072013-10-14 09:55:32 -07004441 if (window > interval)
4442 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4443 MGMT_STATUS_INVALID_PARAMS);
4444
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004445 hci_dev_lock(hdev);
4446
4447 hdev->le_scan_interval = interval;
4448 hdev->le_scan_window = window;
4449
4450 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4451
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004452 /* If background scan is running, restart it so new parameters are
4453 * loaded.
4454 */
4455 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4456 hdev->discovery.state == DISCOVERY_STOPPED) {
4457 struct hci_request req;
4458
4459 hci_req_init(&req, hdev);
4460
4461 hci_req_add_le_scan_disable(&req);
4462 hci_req_add_le_passive_scan(&req);
4463
4464 hci_req_run(&req, NULL);
4465 }
4466
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004467 hci_dev_unlock(hdev);
4468
4469 return err;
4470}
4471
Johan Hedberg33e38b32013-03-15 17:07:05 -05004472static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4473{
4474 struct pending_cmd *cmd;
4475
4476 BT_DBG("status 0x%02x", status);
4477
4478 hci_dev_lock(hdev);
4479
4480 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4481 if (!cmd)
4482 goto unlock;
4483
4484 if (status) {
4485 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4486 mgmt_status(status));
4487 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004488 struct mgmt_mode *cp = cmd->param;
4489
4490 if (cp->val)
4491 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4492 else
4493 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4494
Johan Hedberg33e38b32013-03-15 17:07:05 -05004495 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4496 new_settings(hdev, cmd->sk);
4497 }
4498
4499 mgmt_pending_remove(cmd);
4500
4501unlock:
4502 hci_dev_unlock(hdev);
4503}
4504
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004505static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004506 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004507{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004508 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004509 struct pending_cmd *cmd;
4510 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004511 int err;
4512
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004513 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004514
Johan Hedberg56f87902013-10-02 13:43:13 +03004515 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4516 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004517 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4518 MGMT_STATUS_NOT_SUPPORTED);
4519
Johan Hedberga7e80f22013-01-09 16:05:19 +02004520 if (cp->val != 0x00 && cp->val != 0x01)
4521 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4522 MGMT_STATUS_INVALID_PARAMS);
4523
Johan Hedberg5400c042012-02-21 16:40:33 +02004524 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004525 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004526 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004527
4528 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004529 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004530 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004531
4532 hci_dev_lock(hdev);
4533
Johan Hedberg05cbf292013-03-15 17:07:07 -05004534 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4535 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4536 MGMT_STATUS_BUSY);
4537 goto unlock;
4538 }
4539
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004540 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4541 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4542 hdev);
4543 goto unlock;
4544 }
4545
Johan Hedberg33e38b32013-03-15 17:07:05 -05004546 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4547 data, len);
4548 if (!cmd) {
4549 err = -ENOMEM;
4550 goto unlock;
4551 }
4552
4553 hci_req_init(&req, hdev);
4554
Johan Hedberg406d7802013-03-15 17:07:09 -05004555 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004556
4557 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004558 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004559 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004560 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004561 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004562 }
4563
Johan Hedberg33e38b32013-03-15 17:07:05 -05004564unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004565 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004566
Antti Julkuf6422ec2011-06-22 13:11:56 +03004567 return err;
4568}
4569
Johan Hedberg0663ca22013-10-02 13:43:14 +03004570static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4571{
4572 struct pending_cmd *cmd;
4573
4574 BT_DBG("status 0x%02x", status);
4575
4576 hci_dev_lock(hdev);
4577
4578 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4579 if (!cmd)
4580 goto unlock;
4581
4582 if (status) {
4583 u8 mgmt_err = mgmt_status(status);
4584
4585 /* We need to restore the flag if related HCI commands
4586 * failed.
4587 */
4588 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4589
4590 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4591 } else {
4592 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4593 new_settings(hdev, cmd->sk);
4594 }
4595
4596 mgmt_pending_remove(cmd);
4597
4598unlock:
4599 hci_dev_unlock(hdev);
4600}
4601
4602static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4603{
4604 struct mgmt_mode *cp = data;
4605 struct pending_cmd *cmd;
4606 struct hci_request req;
4607 int err;
4608
4609 BT_DBG("request for %s", hdev->name);
4610
4611 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4612 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4613 MGMT_STATUS_NOT_SUPPORTED);
4614
4615 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4616 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4617 MGMT_STATUS_REJECTED);
4618
4619 if (cp->val != 0x00 && cp->val != 0x01)
4620 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4621 MGMT_STATUS_INVALID_PARAMS);
4622
4623 hci_dev_lock(hdev);
4624
4625 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4626 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4627 goto unlock;
4628 }
4629
4630 if (!hdev_is_powered(hdev)) {
4631 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004632 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4633 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4634 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4635 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4636 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4637 }
4638
4639 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4640
4641 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4642 if (err < 0)
4643 goto unlock;
4644
4645 err = new_settings(hdev, sk);
4646 goto unlock;
4647 }
4648
4649 /* Reject disabling when powered on */
4650 if (!cp->val) {
4651 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4652 MGMT_STATUS_REJECTED);
4653 goto unlock;
4654 }
4655
4656 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4657 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4658 MGMT_STATUS_BUSY);
4659 goto unlock;
4660 }
4661
4662 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4663 if (!cmd) {
4664 err = -ENOMEM;
4665 goto unlock;
4666 }
4667
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004668 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004669 * generates the correct flags.
4670 */
4671 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4672
4673 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004674
Johan Hedberg432df052014-08-01 11:13:31 +03004675 write_fast_connectable(&req, false);
4676 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004677
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004678 /* Since only the advertising data flags will change, there
4679 * is no need to update the scan response data.
4680 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004681 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004682
Johan Hedberg0663ca22013-10-02 13:43:14 +03004683 err = hci_req_run(&req, set_bredr_complete);
4684 if (err < 0)
4685 mgmt_pending_remove(cmd);
4686
4687unlock:
4688 hci_dev_unlock(hdev);
4689 return err;
4690}
4691
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004692static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4693 void *data, u16 len)
4694{
4695 struct mgmt_mode *cp = data;
4696 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004697 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004698 int err;
4699
4700 BT_DBG("request for %s", hdev->name);
4701
Johan Hedberga3209692014-05-26 11:23:35 +03004702 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4703 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004704 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4705 MGMT_STATUS_NOT_SUPPORTED);
4706
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004707 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004708 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4709 MGMT_STATUS_INVALID_PARAMS);
4710
4711 hci_dev_lock(hdev);
4712
Johan Hedberga3209692014-05-26 11:23:35 +03004713 if (!hdev_is_powered(hdev) ||
4714 (!lmp_sc_capable(hdev) &&
4715 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4716 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004717 bool changed;
4718
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004719 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004720 changed = !test_and_set_bit(HCI_SC_ENABLED,
4721 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004722 if (cp->val == 0x02)
4723 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4724 else
4725 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4726 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004727 changed = test_and_clear_bit(HCI_SC_ENABLED,
4728 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004729 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4730 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004731
4732 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4733 if (err < 0)
4734 goto failed;
4735
4736 if (changed)
4737 err = new_settings(hdev, sk);
4738
4739 goto failed;
4740 }
4741
4742 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4743 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4744 MGMT_STATUS_BUSY);
4745 goto failed;
4746 }
4747
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004748 val = !!cp->val;
4749
4750 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4751 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004752 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4753 goto failed;
4754 }
4755
4756 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4757 if (!cmd) {
4758 err = -ENOMEM;
4759 goto failed;
4760 }
4761
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004762 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004763 if (err < 0) {
4764 mgmt_pending_remove(cmd);
4765 goto failed;
4766 }
4767
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004768 if (cp->val == 0x02)
4769 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4770 else
4771 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4772
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004773failed:
4774 hci_dev_unlock(hdev);
4775 return err;
4776}
4777
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004778static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4779 void *data, u16 len)
4780{
4781 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004782 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004783 int err;
4784
4785 BT_DBG("request for %s", hdev->name);
4786
Johan Hedbergb97109792014-06-24 14:00:28 +03004787 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004788 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4789 MGMT_STATUS_INVALID_PARAMS);
4790
4791 hci_dev_lock(hdev);
4792
4793 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004794 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4795 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004796 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004797 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4798 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004799
Johan Hedbergb97109792014-06-24 14:00:28 +03004800 if (cp->val == 0x02)
4801 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4802 &hdev->dev_flags);
4803 else
4804 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4805 &hdev->dev_flags);
4806
4807 if (hdev_is_powered(hdev) && use_changed &&
4808 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4809 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4810 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4811 sizeof(mode), &mode);
4812 }
4813
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004814 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4815 if (err < 0)
4816 goto unlock;
4817
4818 if (changed)
4819 err = new_settings(hdev, sk);
4820
4821unlock:
4822 hci_dev_unlock(hdev);
4823 return err;
4824}
4825
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004826static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4827 u16 len)
4828{
4829 struct mgmt_cp_set_privacy *cp = cp_data;
4830 bool changed;
4831 int err;
4832
4833 BT_DBG("request for %s", hdev->name);
4834
4835 if (!lmp_le_capable(hdev))
4836 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4837 MGMT_STATUS_NOT_SUPPORTED);
4838
4839 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4840 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4841 MGMT_STATUS_INVALID_PARAMS);
4842
4843 if (hdev_is_powered(hdev))
4844 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4845 MGMT_STATUS_REJECTED);
4846
4847 hci_dev_lock(hdev);
4848
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004849 /* If user space supports this command it is also expected to
4850 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4851 */
4852 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4853
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004854 if (cp->privacy) {
4855 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4856 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4857 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4858 } else {
4859 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4860 memset(hdev->irk, 0, sizeof(hdev->irk));
4861 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4862 }
4863
4864 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4865 if (err < 0)
4866 goto unlock;
4867
4868 if (changed)
4869 err = new_settings(hdev, sk);
4870
4871unlock:
4872 hci_dev_unlock(hdev);
4873 return err;
4874}
4875
Johan Hedberg41edf162014-02-18 10:19:35 +02004876static bool irk_is_valid(struct mgmt_irk_info *irk)
4877{
4878 switch (irk->addr.type) {
4879 case BDADDR_LE_PUBLIC:
4880 return true;
4881
4882 case BDADDR_LE_RANDOM:
4883 /* Two most significant bits shall be set */
4884 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4885 return false;
4886 return true;
4887 }
4888
4889 return false;
4890}
4891
4892static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4893 u16 len)
4894{
4895 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004896 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4897 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004898 u16 irk_count, expected_len;
4899 int i, err;
4900
4901 BT_DBG("request for %s", hdev->name);
4902
4903 if (!lmp_le_capable(hdev))
4904 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4905 MGMT_STATUS_NOT_SUPPORTED);
4906
4907 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004908 if (irk_count > max_irk_count) {
4909 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4910 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4911 MGMT_STATUS_INVALID_PARAMS);
4912 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004913
4914 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4915 if (expected_len != len) {
4916 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004917 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004918 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4919 MGMT_STATUS_INVALID_PARAMS);
4920 }
4921
4922 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4923
4924 for (i = 0; i < irk_count; i++) {
4925 struct mgmt_irk_info *key = &cp->irks[i];
4926
4927 if (!irk_is_valid(key))
4928 return cmd_status(sk, hdev->id,
4929 MGMT_OP_LOAD_IRKS,
4930 MGMT_STATUS_INVALID_PARAMS);
4931 }
4932
4933 hci_dev_lock(hdev);
4934
4935 hci_smp_irks_clear(hdev);
4936
4937 for (i = 0; i < irk_count; i++) {
4938 struct mgmt_irk_info *irk = &cp->irks[i];
4939 u8 addr_type;
4940
4941 if (irk->addr.type == BDADDR_LE_PUBLIC)
4942 addr_type = ADDR_LE_DEV_PUBLIC;
4943 else
4944 addr_type = ADDR_LE_DEV_RANDOM;
4945
4946 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4947 BDADDR_ANY);
4948 }
4949
4950 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4951
4952 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4953
4954 hci_dev_unlock(hdev);
4955
4956 return err;
4957}
4958
Johan Hedberg3f706b72013-01-20 14:27:16 +02004959static bool ltk_is_valid(struct mgmt_ltk_info *key)
4960{
4961 if (key->master != 0x00 && key->master != 0x01)
4962 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004963
4964 switch (key->addr.type) {
4965 case BDADDR_LE_PUBLIC:
4966 return true;
4967
4968 case BDADDR_LE_RANDOM:
4969 /* Two most significant bits shall be set */
4970 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4971 return false;
4972 return true;
4973 }
4974
4975 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004976}
4977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004978static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004979 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004980{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004981 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004982 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4983 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004984 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004985 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004986
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004987 BT_DBG("request for %s", hdev->name);
4988
4989 if (!lmp_le_capable(hdev))
4990 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4991 MGMT_STATUS_NOT_SUPPORTED);
4992
Marcel Holtmann1f350c82012-03-12 20:31:08 -07004993 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004994 if (key_count > max_key_count) {
4995 BT_ERR("load_ltks: too big key_count value %u", key_count);
4996 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4997 MGMT_STATUS_INVALID_PARAMS);
4998 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004999
5000 expected_len = sizeof(*cp) + key_count *
5001 sizeof(struct mgmt_ltk_info);
5002 if (expected_len != len) {
5003 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005004 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005005 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005006 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005007 }
5008
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005009 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005010
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005011 for (i = 0; i < key_count; i++) {
5012 struct mgmt_ltk_info *key = &cp->keys[i];
5013
Johan Hedberg3f706b72013-01-20 14:27:16 +02005014 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005015 return cmd_status(sk, hdev->id,
5016 MGMT_OP_LOAD_LONG_TERM_KEYS,
5017 MGMT_STATUS_INVALID_PARAMS);
5018 }
5019
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005020 hci_dev_lock(hdev);
5021
5022 hci_smp_ltks_clear(hdev);
5023
5024 for (i = 0; i < key_count; i++) {
5025 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005026 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005027
5028 if (key->addr.type == BDADDR_LE_PUBLIC)
5029 addr_type = ADDR_LE_DEV_PUBLIC;
5030 else
5031 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005032
Johan Hedberg61b43352014-05-29 19:36:53 +03005033 switch (key->type) {
5034 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005035 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005036 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005037 break;
5038 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005039 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005040 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005041 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005042 case MGMT_LTK_P256_UNAUTH:
5043 authenticated = 0x00;
5044 type = SMP_LTK_P256;
5045 break;
5046 case MGMT_LTK_P256_AUTH:
5047 authenticated = 0x01;
5048 type = SMP_LTK_P256;
5049 break;
5050 case MGMT_LTK_P256_DEBUG:
5051 authenticated = 0x00;
5052 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005053 default:
5054 continue;
5055 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005056
Johan Hedberg35d70272014-02-19 14:57:47 +02005057 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005058 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005059 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005060 }
5061
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005062 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5063 NULL, 0);
5064
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005065 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005066
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005067 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005068}
5069
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005070struct cmd_conn_lookup {
5071 struct hci_conn *conn;
5072 bool valid_tx_power;
5073 u8 mgmt_status;
5074};
5075
5076static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5077{
5078 struct cmd_conn_lookup *match = data;
5079 struct mgmt_cp_get_conn_info *cp;
5080 struct mgmt_rp_get_conn_info rp;
5081 struct hci_conn *conn = cmd->user_data;
5082
5083 if (conn != match->conn)
5084 return;
5085
5086 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5087
5088 memset(&rp, 0, sizeof(rp));
5089 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5090 rp.addr.type = cp->addr.type;
5091
5092 if (!match->mgmt_status) {
5093 rp.rssi = conn->rssi;
5094
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005095 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005096 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005097 rp.max_tx_power = conn->max_tx_power;
5098 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005099 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005100 rp.max_tx_power = HCI_TX_POWER_INVALID;
5101 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005102 }
5103
5104 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5105 match->mgmt_status, &rp, sizeof(rp));
5106
5107 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005108 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005109
5110 mgmt_pending_remove(cmd);
5111}
5112
5113static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5114{
5115 struct hci_cp_read_rssi *cp;
5116 struct hci_conn *conn;
5117 struct cmd_conn_lookup match;
5118 u16 handle;
5119
5120 BT_DBG("status 0x%02x", status);
5121
5122 hci_dev_lock(hdev);
5123
5124 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005125 * otherwise we assume it's not valid. At the moment we assume that
5126 * either both or none of current and max values are valid to keep code
5127 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005128 */
5129 match.valid_tx_power = !status;
5130
5131 /* Commands sent in request are either Read RSSI or Read Transmit Power
5132 * Level so we check which one was last sent to retrieve connection
5133 * handle. Both commands have handle as first parameter so it's safe to
5134 * cast data on the same command struct.
5135 *
5136 * First command sent is always Read RSSI and we fail only if it fails.
5137 * In other case we simply override error to indicate success as we
5138 * already remembered if TX power value is actually valid.
5139 */
5140 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5141 if (!cp) {
5142 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5143 status = 0;
5144 }
5145
5146 if (!cp) {
5147 BT_ERR("invalid sent_cmd in response");
5148 goto unlock;
5149 }
5150
5151 handle = __le16_to_cpu(cp->handle);
5152 conn = hci_conn_hash_lookup_handle(hdev, handle);
5153 if (!conn) {
5154 BT_ERR("unknown handle (%d) in response", handle);
5155 goto unlock;
5156 }
5157
5158 match.conn = conn;
5159 match.mgmt_status = mgmt_status(status);
5160
5161 /* Cache refresh is complete, now reply for mgmt request for given
5162 * connection only.
5163 */
5164 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5165 get_conn_info_complete, &match);
5166
5167unlock:
5168 hci_dev_unlock(hdev);
5169}
5170
5171static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5172 u16 len)
5173{
5174 struct mgmt_cp_get_conn_info *cp = data;
5175 struct mgmt_rp_get_conn_info rp;
5176 struct hci_conn *conn;
5177 unsigned long conn_info_age;
5178 int err = 0;
5179
5180 BT_DBG("%s", hdev->name);
5181
5182 memset(&rp, 0, sizeof(rp));
5183 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5184 rp.addr.type = cp->addr.type;
5185
5186 if (!bdaddr_type_is_valid(cp->addr.type))
5187 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5188 MGMT_STATUS_INVALID_PARAMS,
5189 &rp, sizeof(rp));
5190
5191 hci_dev_lock(hdev);
5192
5193 if (!hdev_is_powered(hdev)) {
5194 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5195 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5196 goto unlock;
5197 }
5198
5199 if (cp->addr.type == BDADDR_BREDR)
5200 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5201 &cp->addr.bdaddr);
5202 else
5203 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5204
5205 if (!conn || conn->state != BT_CONNECTED) {
5206 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5207 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5208 goto unlock;
5209 }
5210
5211 /* To avoid client trying to guess when to poll again for information we
5212 * calculate conn info age as random value between min/max set in hdev.
5213 */
5214 conn_info_age = hdev->conn_info_min_age +
5215 prandom_u32_max(hdev->conn_info_max_age -
5216 hdev->conn_info_min_age);
5217
5218 /* Query controller to refresh cached values if they are too old or were
5219 * never read.
5220 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005221 if (time_after(jiffies, conn->conn_info_timestamp +
5222 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005223 !conn->conn_info_timestamp) {
5224 struct hci_request req;
5225 struct hci_cp_read_tx_power req_txp_cp;
5226 struct hci_cp_read_rssi req_rssi_cp;
5227 struct pending_cmd *cmd;
5228
5229 hci_req_init(&req, hdev);
5230 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5231 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5232 &req_rssi_cp);
5233
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005234 /* For LE links TX power does not change thus we don't need to
5235 * query for it once value is known.
5236 */
5237 if (!bdaddr_type_is_le(cp->addr.type) ||
5238 conn->tx_power == HCI_TX_POWER_INVALID) {
5239 req_txp_cp.handle = cpu_to_le16(conn->handle);
5240 req_txp_cp.type = 0x00;
5241 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5242 sizeof(req_txp_cp), &req_txp_cp);
5243 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005244
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005245 /* Max TX power needs to be read only once per connection */
5246 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5247 req_txp_cp.handle = cpu_to_le16(conn->handle);
5248 req_txp_cp.type = 0x01;
5249 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5250 sizeof(req_txp_cp), &req_txp_cp);
5251 }
5252
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005253 err = hci_req_run(&req, conn_info_refresh_complete);
5254 if (err < 0)
5255 goto unlock;
5256
5257 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5258 data, len);
5259 if (!cmd) {
5260 err = -ENOMEM;
5261 goto unlock;
5262 }
5263
5264 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005265 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005266
5267 conn->conn_info_timestamp = jiffies;
5268 } else {
5269 /* Cache is valid, just reply with values cached in hci_conn */
5270 rp.rssi = conn->rssi;
5271 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005272 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005273
5274 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5275 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5276 }
5277
5278unlock:
5279 hci_dev_unlock(hdev);
5280 return err;
5281}
5282
Johan Hedberg95868422014-06-28 17:54:07 +03005283static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5284{
5285 struct mgmt_cp_get_clock_info *cp;
5286 struct mgmt_rp_get_clock_info rp;
5287 struct hci_cp_read_clock *hci_cp;
5288 struct pending_cmd *cmd;
5289 struct hci_conn *conn;
5290
5291 BT_DBG("%s status %u", hdev->name, status);
5292
5293 hci_dev_lock(hdev);
5294
5295 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5296 if (!hci_cp)
5297 goto unlock;
5298
5299 if (hci_cp->which) {
5300 u16 handle = __le16_to_cpu(hci_cp->handle);
5301 conn = hci_conn_hash_lookup_handle(hdev, handle);
5302 } else {
5303 conn = NULL;
5304 }
5305
5306 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5307 if (!cmd)
5308 goto unlock;
5309
5310 cp = cmd->param;
5311
5312 memset(&rp, 0, sizeof(rp));
5313 memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
5314
5315 if (status)
5316 goto send_rsp;
5317
5318 rp.local_clock = cpu_to_le32(hdev->clock);
5319
5320 if (conn) {
5321 rp.piconet_clock = cpu_to_le32(conn->clock);
5322 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5323 }
5324
5325send_rsp:
5326 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
5327 &rp, sizeof(rp));
5328 mgmt_pending_remove(cmd);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005329 if (conn) {
Johan Hedberg95868422014-06-28 17:54:07 +03005330 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005331 hci_conn_put(conn);
5332 }
Johan Hedberg95868422014-06-28 17:54:07 +03005333
5334unlock:
5335 hci_dev_unlock(hdev);
5336}
5337
5338static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5339 u16 len)
5340{
5341 struct mgmt_cp_get_clock_info *cp = data;
5342 struct mgmt_rp_get_clock_info rp;
5343 struct hci_cp_read_clock hci_cp;
5344 struct pending_cmd *cmd;
5345 struct hci_request req;
5346 struct hci_conn *conn;
5347 int err;
5348
5349 BT_DBG("%s", hdev->name);
5350
5351 memset(&rp, 0, sizeof(rp));
5352 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5353 rp.addr.type = cp->addr.type;
5354
5355 if (cp->addr.type != BDADDR_BREDR)
5356 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5357 MGMT_STATUS_INVALID_PARAMS,
5358 &rp, sizeof(rp));
5359
5360 hci_dev_lock(hdev);
5361
5362 if (!hdev_is_powered(hdev)) {
5363 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5364 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5365 goto unlock;
5366 }
5367
5368 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5369 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5370 &cp->addr.bdaddr);
5371 if (!conn || conn->state != BT_CONNECTED) {
5372 err = cmd_complete(sk, hdev->id,
5373 MGMT_OP_GET_CLOCK_INFO,
5374 MGMT_STATUS_NOT_CONNECTED,
5375 &rp, sizeof(rp));
5376 goto unlock;
5377 }
5378 } else {
5379 conn = NULL;
5380 }
5381
5382 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5383 if (!cmd) {
5384 err = -ENOMEM;
5385 goto unlock;
5386 }
5387
5388 hci_req_init(&req, hdev);
5389
5390 memset(&hci_cp, 0, sizeof(hci_cp));
5391 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5392
5393 if (conn) {
5394 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005395 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005396
5397 hci_cp.handle = cpu_to_le16(conn->handle);
5398 hci_cp.which = 0x01; /* Piconet clock */
5399 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5400 }
5401
5402 err = hci_req_run(&req, get_clock_info_complete);
5403 if (err < 0)
5404 mgmt_pending_remove(cmd);
5405
5406unlock:
5407 hci_dev_unlock(hdev);
5408 return err;
5409}
5410
Marcel Holtmann8afef092014-06-29 22:28:34 +02005411static void device_added(struct sock *sk, struct hci_dev *hdev,
5412 bdaddr_t *bdaddr, u8 type, u8 action)
5413{
5414 struct mgmt_ev_device_added ev;
5415
5416 bacpy(&ev.addr.bdaddr, bdaddr);
5417 ev.addr.type = type;
5418 ev.action = action;
5419
5420 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5421}
5422
Marcel Holtmann2faade52014-06-29 19:44:03 +02005423static int add_device(struct sock *sk, struct hci_dev *hdev,
5424 void *data, u16 len)
5425{
5426 struct mgmt_cp_add_device *cp = data;
5427 u8 auto_conn, addr_type;
5428 int err;
5429
5430 BT_DBG("%s", hdev->name);
5431
Johan Hedberg66593582014-07-09 12:59:14 +03005432 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005433 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5434 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5435 MGMT_STATUS_INVALID_PARAMS,
5436 &cp->addr, sizeof(cp->addr));
5437
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005438 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005439 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5440 MGMT_STATUS_INVALID_PARAMS,
5441 &cp->addr, sizeof(cp->addr));
5442
5443 hci_dev_lock(hdev);
5444
Johan Hedberg66593582014-07-09 12:59:14 +03005445 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005446 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005447 if (cp->action != 0x01) {
5448 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5449 MGMT_STATUS_INVALID_PARAMS,
5450 &cp->addr, sizeof(cp->addr));
5451 goto unlock;
5452 }
5453
5454 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5455 cp->addr.type);
5456 if (err)
5457 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005458
Johan Hedberg432df052014-08-01 11:13:31 +03005459 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005460
Johan Hedberg66593582014-07-09 12:59:14 +03005461 goto added;
5462 }
5463
Marcel Holtmann2faade52014-06-29 19:44:03 +02005464 if (cp->addr.type == BDADDR_LE_PUBLIC)
5465 addr_type = ADDR_LE_DEV_PUBLIC;
5466 else
5467 addr_type = ADDR_LE_DEV_RANDOM;
5468
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005469 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005470 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005471 else if (cp->action == 0x01)
5472 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005473 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005474 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005475
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005476 /* If the connection parameters don't exist for this device,
5477 * they will be created and configured with defaults.
5478 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005479 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5480 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005481 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5482 MGMT_STATUS_FAILED,
5483 &cp->addr, sizeof(cp->addr));
5484 goto unlock;
5485 }
5486
Johan Hedberg66593582014-07-09 12:59:14 +03005487added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005488 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5489
Marcel Holtmann2faade52014-06-29 19:44:03 +02005490 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5491 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5492
5493unlock:
5494 hci_dev_unlock(hdev);
5495 return err;
5496}
5497
Marcel Holtmann8afef092014-06-29 22:28:34 +02005498static void device_removed(struct sock *sk, struct hci_dev *hdev,
5499 bdaddr_t *bdaddr, u8 type)
5500{
5501 struct mgmt_ev_device_removed ev;
5502
5503 bacpy(&ev.addr.bdaddr, bdaddr);
5504 ev.addr.type = type;
5505
5506 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5507}
5508
Marcel Holtmann2faade52014-06-29 19:44:03 +02005509static int remove_device(struct sock *sk, struct hci_dev *hdev,
5510 void *data, u16 len)
5511{
5512 struct mgmt_cp_remove_device *cp = data;
5513 int err;
5514
5515 BT_DBG("%s", hdev->name);
5516
5517 hci_dev_lock(hdev);
5518
5519 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005520 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005521 u8 addr_type;
5522
Johan Hedberg66593582014-07-09 12:59:14 +03005523 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005524 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5525 MGMT_STATUS_INVALID_PARAMS,
5526 &cp->addr, sizeof(cp->addr));
5527 goto unlock;
5528 }
5529
Johan Hedberg66593582014-07-09 12:59:14 +03005530 if (cp->addr.type == BDADDR_BREDR) {
5531 err = hci_bdaddr_list_del(&hdev->whitelist,
5532 &cp->addr.bdaddr,
5533 cp->addr.type);
5534 if (err) {
5535 err = cmd_complete(sk, hdev->id,
5536 MGMT_OP_REMOVE_DEVICE,
5537 MGMT_STATUS_INVALID_PARAMS,
5538 &cp->addr, sizeof(cp->addr));
5539 goto unlock;
5540 }
5541
Johan Hedberg432df052014-08-01 11:13:31 +03005542 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005543
Johan Hedberg66593582014-07-09 12:59:14 +03005544 device_removed(sk, hdev, &cp->addr.bdaddr,
5545 cp->addr.type);
5546 goto complete;
5547 }
5548
Marcel Holtmann2faade52014-06-29 19:44:03 +02005549 if (cp->addr.type == BDADDR_LE_PUBLIC)
5550 addr_type = ADDR_LE_DEV_PUBLIC;
5551 else
5552 addr_type = ADDR_LE_DEV_RANDOM;
5553
Johan Hedbergc71593d2014-07-02 17:37:28 +03005554 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5555 addr_type);
5556 if (!params) {
5557 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5558 MGMT_STATUS_INVALID_PARAMS,
5559 &cp->addr, sizeof(cp->addr));
5560 goto unlock;
5561 }
5562
5563 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5564 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5565 MGMT_STATUS_INVALID_PARAMS,
5566 &cp->addr, sizeof(cp->addr));
5567 goto unlock;
5568 }
5569
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005570 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005571 list_del(&params->list);
5572 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005573 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005574
5575 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005576 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005577 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005578 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005579
Marcel Holtmann2faade52014-06-29 19:44:03 +02005580 if (cp->addr.type) {
5581 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5582 MGMT_STATUS_INVALID_PARAMS,
5583 &cp->addr, sizeof(cp->addr));
5584 goto unlock;
5585 }
5586
Johan Hedberg66593582014-07-09 12:59:14 +03005587 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5588 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5589 list_del(&b->list);
5590 kfree(b);
5591 }
5592
Johan Hedberg432df052014-08-01 11:13:31 +03005593 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005594
Johan Hedberg19de0822014-07-06 13:06:51 +03005595 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5596 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5597 continue;
5598 device_removed(sk, hdev, &p->addr, p->addr_type);
5599 list_del(&p->action);
5600 list_del(&p->list);
5601 kfree(p);
5602 }
5603
5604 BT_DBG("All LE connection parameters were removed");
5605
5606 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005607 }
5608
Johan Hedberg66593582014-07-09 12:59:14 +03005609complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005610 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5611 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5612
5613unlock:
5614 hci_dev_unlock(hdev);
5615 return err;
5616}
5617
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005618static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5619 u16 len)
5620{
5621 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005622 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5623 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005624 u16 param_count, expected_len;
5625 int i;
5626
5627 if (!lmp_le_capable(hdev))
5628 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5629 MGMT_STATUS_NOT_SUPPORTED);
5630
5631 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005632 if (param_count > max_param_count) {
5633 BT_ERR("load_conn_param: too big param_count value %u",
5634 param_count);
5635 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5636 MGMT_STATUS_INVALID_PARAMS);
5637 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005638
5639 expected_len = sizeof(*cp) + param_count *
5640 sizeof(struct mgmt_conn_param);
5641 if (expected_len != len) {
5642 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5643 expected_len, len);
5644 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5645 MGMT_STATUS_INVALID_PARAMS);
5646 }
5647
5648 BT_DBG("%s param_count %u", hdev->name, param_count);
5649
5650 hci_dev_lock(hdev);
5651
5652 hci_conn_params_clear_disabled(hdev);
5653
5654 for (i = 0; i < param_count; i++) {
5655 struct mgmt_conn_param *param = &cp->params[i];
5656 struct hci_conn_params *hci_param;
5657 u16 min, max, latency, timeout;
5658 u8 addr_type;
5659
5660 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5661 param->addr.type);
5662
5663 if (param->addr.type == BDADDR_LE_PUBLIC) {
5664 addr_type = ADDR_LE_DEV_PUBLIC;
5665 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5666 addr_type = ADDR_LE_DEV_RANDOM;
5667 } else {
5668 BT_ERR("Ignoring invalid connection parameters");
5669 continue;
5670 }
5671
5672 min = le16_to_cpu(param->min_interval);
5673 max = le16_to_cpu(param->max_interval);
5674 latency = le16_to_cpu(param->latency);
5675 timeout = le16_to_cpu(param->timeout);
5676
5677 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5678 min, max, latency, timeout);
5679
5680 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5681 BT_ERR("Ignoring invalid connection parameters");
5682 continue;
5683 }
5684
5685 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5686 addr_type);
5687 if (!hci_param) {
5688 BT_ERR("Failed to add connection parameters");
5689 continue;
5690 }
5691
5692 hci_param->conn_min_interval = min;
5693 hci_param->conn_max_interval = max;
5694 hci_param->conn_latency = latency;
5695 hci_param->supervision_timeout = timeout;
5696 }
5697
5698 hci_dev_unlock(hdev);
5699
5700 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5701}
5702
Marcel Holtmanndbece372014-07-04 18:11:55 +02005703static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5704 void *data, u16 len)
5705{
5706 struct mgmt_cp_set_external_config *cp = data;
5707 bool changed;
5708 int err;
5709
5710 BT_DBG("%s", hdev->name);
5711
5712 if (hdev_is_powered(hdev))
5713 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5714 MGMT_STATUS_REJECTED);
5715
5716 if (cp->config != 0x00 && cp->config != 0x01)
5717 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5718 MGMT_STATUS_INVALID_PARAMS);
5719
5720 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5721 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5722 MGMT_STATUS_NOT_SUPPORTED);
5723
5724 hci_dev_lock(hdev);
5725
5726 if (cp->config)
5727 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5728 &hdev->dev_flags);
5729 else
5730 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5731 &hdev->dev_flags);
5732
5733 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5734 if (err < 0)
5735 goto unlock;
5736
5737 if (!changed)
5738 goto unlock;
5739
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005740 err = new_options(hdev, sk);
5741
Marcel Holtmanndbece372014-07-04 18:11:55 +02005742 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5743 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005744
5745 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5746 set_bit(HCI_CONFIG, &hdev->dev_flags);
5747 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5748
5749 queue_work(hdev->req_workqueue, &hdev->power_on);
5750 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005751 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005752 mgmt_index_added(hdev);
5753 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005754 }
5755
5756unlock:
5757 hci_dev_unlock(hdev);
5758 return err;
5759}
5760
Marcel Holtmann9713c172014-07-06 12:11:15 +02005761static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5762 void *data, u16 len)
5763{
5764 struct mgmt_cp_set_public_address *cp = data;
5765 bool changed;
5766 int err;
5767
5768 BT_DBG("%s", hdev->name);
5769
5770 if (hdev_is_powered(hdev))
5771 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5772 MGMT_STATUS_REJECTED);
5773
5774 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5775 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5776 MGMT_STATUS_INVALID_PARAMS);
5777
5778 if (!hdev->set_bdaddr)
5779 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5780 MGMT_STATUS_NOT_SUPPORTED);
5781
5782 hci_dev_lock(hdev);
5783
5784 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5785 bacpy(&hdev->public_addr, &cp->bdaddr);
5786
5787 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5788 if (err < 0)
5789 goto unlock;
5790
5791 if (!changed)
5792 goto unlock;
5793
5794 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5795 err = new_options(hdev, sk);
5796
5797 if (is_configured(hdev)) {
5798 mgmt_index_removed(hdev);
5799
5800 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5801
5802 set_bit(HCI_CONFIG, &hdev->dev_flags);
5803 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5804
5805 queue_work(hdev->req_workqueue, &hdev->power_on);
5806 }
5807
5808unlock:
5809 hci_dev_unlock(hdev);
5810 return err;
5811}
5812
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005813static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005814 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5815 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005816 bool var_len;
5817 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005818} mgmt_handlers[] = {
5819 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005820 { read_version, false, MGMT_READ_VERSION_SIZE },
5821 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5822 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5823 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5824 { set_powered, false, MGMT_SETTING_SIZE },
5825 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5826 { set_connectable, false, MGMT_SETTING_SIZE },
5827 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005828 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005829 { set_link_security, false, MGMT_SETTING_SIZE },
5830 { set_ssp, false, MGMT_SETTING_SIZE },
5831 { set_hs, false, MGMT_SETTING_SIZE },
5832 { set_le, false, MGMT_SETTING_SIZE },
5833 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5834 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5835 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5836 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5837 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5838 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5839 { disconnect, false, MGMT_DISCONNECT_SIZE },
5840 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5841 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5842 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5843 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5844 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5845 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5846 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5847 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5848 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5849 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5850 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5851 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005852 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005853 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5854 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5855 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5856 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5857 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5858 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005859 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005860 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005861 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005862 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005863 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005864 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005865 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005866 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005867 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005868 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005869 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005870 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5871 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005872 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5873 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005874 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005875 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005876 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005877 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005878};
5879
Johan Hedberg03811012010-12-08 00:21:06 +02005880int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5881{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005882 void *buf;
5883 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005884 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005885 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005886 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005887 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005888 int err;
5889
5890 BT_DBG("got %zu bytes", msglen);
5891
5892 if (msglen < sizeof(*hdr))
5893 return -EINVAL;
5894
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005895 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005896 if (!buf)
5897 return -ENOMEM;
5898
5899 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5900 err = -EFAULT;
5901 goto done;
5902 }
5903
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005904 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005905 opcode = __le16_to_cpu(hdr->opcode);
5906 index = __le16_to_cpu(hdr->index);
5907 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005908
5909 if (len != msglen - sizeof(*hdr)) {
5910 err = -EINVAL;
5911 goto done;
5912 }
5913
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005914 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005915 hdev = hci_dev_get(index);
5916 if (!hdev) {
5917 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005918 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005919 goto done;
5920 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005921
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005922 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005923 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005924 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005925 err = cmd_status(sk, index, opcode,
5926 MGMT_STATUS_INVALID_INDEX);
5927 goto done;
5928 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005929
5930 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005931 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005932 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5933 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005934 err = cmd_status(sk, index, opcode,
5935 MGMT_STATUS_INVALID_INDEX);
5936 goto done;
5937 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005938 }
5939
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005940 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005941 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005942 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005943 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005944 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005945 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005946 }
5947
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005948 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5949 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5950 err = cmd_status(sk, index, opcode,
5951 MGMT_STATUS_INVALID_INDEX);
5952 goto done;
5953 }
5954
5955 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5956 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005957 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005958 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005959 goto done;
5960 }
5961
Johan Hedbergbe22b542012-03-01 22:24:41 +02005962 handler = &mgmt_handlers[opcode];
5963
5964 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005965 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005966 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005967 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005968 goto done;
5969 }
5970
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005971 if (hdev)
5972 mgmt_init_hdev(sk, hdev);
5973
5974 cp = buf + sizeof(*hdr);
5975
Johan Hedbergbe22b542012-03-01 22:24:41 +02005976 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005977 if (err < 0)
5978 goto done;
5979
Johan Hedberg03811012010-12-08 00:21:06 +02005980 err = msglen;
5981
5982done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005983 if (hdev)
5984 hci_dev_put(hdev);
5985
Johan Hedberg03811012010-12-08 00:21:06 +02005986 kfree(buf);
5987 return err;
5988}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005989
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005990void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005991{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005992 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005993 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03005994
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02005995 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
5996 return;
5997
5998 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5999 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6000 else
6001 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006002}
6003
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006004void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006005{
Johan Hedberg5f159032012-03-02 03:13:19 +02006006 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006007
Marcel Holtmann1514b892013-10-06 08:25:01 -07006008 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006009 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006010
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006011 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6012 return;
6013
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006014 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006015
Marcel Holtmannedd38962014-07-02 21:30:55 +02006016 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6017 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6018 else
6019 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006020}
6021
Andre Guedes6046dc32014-02-26 20:21:51 -03006022/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006023static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006024{
6025 struct hci_conn_params *p;
6026
6027 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006028 /* Needed for AUTO_OFF case where might not "really"
6029 * have been powered off.
6030 */
6031 list_del_init(&p->action);
6032
6033 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006034 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006035 case HCI_AUTO_CONN_ALWAYS:
6036 list_add(&p->action, &hdev->pend_le_conns);
6037 break;
6038 case HCI_AUTO_CONN_REPORT:
6039 list_add(&p->action, &hdev->pend_le_reports);
6040 break;
6041 default:
6042 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006043 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006044 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006045
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006046 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006047}
6048
Johan Hedberg229ab392013-03-15 17:06:53 -05006049static void powered_complete(struct hci_dev *hdev, u8 status)
6050{
6051 struct cmd_lookup match = { NULL, hdev };
6052
6053 BT_DBG("status 0x%02x", status);
6054
6055 hci_dev_lock(hdev);
6056
Johan Hedbergd7347f32014-07-04 12:37:23 +03006057 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006058
Johan Hedberg229ab392013-03-15 17:06:53 -05006059 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6060
6061 new_settings(hdev, match.sk);
6062
6063 hci_dev_unlock(hdev);
6064
6065 if (match.sk)
6066 sock_put(match.sk);
6067}
6068
Johan Hedberg70da6242013-03-15 17:06:51 -05006069static int powered_update_hci(struct hci_dev *hdev)
6070{
Johan Hedberg890ea892013-03-15 17:06:52 -05006071 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006072 u8 link_sec;
6073
Johan Hedberg890ea892013-03-15 17:06:52 -05006074 hci_req_init(&req, hdev);
6075
Johan Hedberg70da6242013-03-15 17:06:51 -05006076 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6077 !lmp_host_ssp_capable(hdev)) {
6078 u8 ssp = 1;
6079
Johan Hedberg890ea892013-03-15 17:06:52 -05006080 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006081 }
6082
Johan Hedbergc73eee92013-04-19 18:35:21 +03006083 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6084 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006085 struct hci_cp_write_le_host_supported cp;
6086
Marcel Holtmann32226e42014-07-24 20:04:16 +02006087 cp.le = 0x01;
6088 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006089
6090 /* Check first if we already have the right
6091 * host state (host features set)
6092 */
6093 if (cp.le != lmp_host_le_capable(hdev) ||
6094 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006095 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6096 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006097 }
6098
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006099 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006100 /* Make sure the controller has a good default for
6101 * advertising data. This also applies to the case
6102 * where BR/EDR was toggled during the AUTO_OFF phase.
6103 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006104 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006105 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006106 update_scan_rsp_data(&req);
6107 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006108
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006109 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6110 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006111 }
6112
Johan Hedberg70da6242013-03-15 17:06:51 -05006113 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6114 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006115 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6116 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006117
6118 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006119 write_fast_connectable(&req, false);
6120 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006121 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006122 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006123 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006124 }
6125
Johan Hedberg229ab392013-03-15 17:06:53 -05006126 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006127}
6128
Johan Hedberg744cf192011-11-08 20:40:14 +02006129int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006130{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006131 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006132 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6133 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006134 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006135
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006136 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6137 return 0;
6138
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006139 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006140 if (powered_update_hci(hdev) == 0)
6141 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006142
Johan Hedberg229ab392013-03-15 17:06:53 -05006143 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6144 &match);
6145 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006146 }
6147
Johan Hedberg229ab392013-03-15 17:06:53 -05006148 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006149 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006150
6151 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6152 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6153 zero_cod, sizeof(zero_cod), NULL);
6154
6155new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006156 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006157
6158 if (match.sk)
6159 sock_put(match.sk);
6160
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006161 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006162}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006163
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006164void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006165{
6166 struct pending_cmd *cmd;
6167 u8 status;
6168
6169 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6170 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006171 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006172
6173 if (err == -ERFKILL)
6174 status = MGMT_STATUS_RFKILLED;
6175 else
6176 status = MGMT_STATUS_FAILED;
6177
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006178 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006179
6180 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006181}
6182
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006183void mgmt_discoverable_timeout(struct hci_dev *hdev)
6184{
6185 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006186
6187 hci_dev_lock(hdev);
6188
6189 /* When discoverable timeout triggers, then just make sure
6190 * the limited discoverable flag is cleared. Even in the case
6191 * of a timeout triggered from general discoverable, it is
6192 * safe to unconditionally clear the flag.
6193 */
6194 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006195 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006196
6197 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006198 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6199 u8 scan = SCAN_PAGE;
6200 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6201 sizeof(scan), &scan);
6202 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006203 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006204 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006205 hci_req_run(&req, NULL);
6206
6207 hdev->discov_timeout = 0;
6208
Johan Hedberg9a43e252013-10-20 19:00:07 +03006209 new_settings(hdev, NULL);
6210
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006211 hci_dev_unlock(hdev);
6212}
6213
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006214void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6215 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006216{
Johan Hedberg86742e12011-11-07 23:13:38 +02006217 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006218
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006219 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006220
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006221 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006222 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006223 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006224 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006225 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006226 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006227
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006228 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006229}
Johan Hedbergf7520542011-01-20 12:34:39 +02006230
Johan Hedbergd7b25452014-05-23 13:19:53 +03006231static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6232{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006233 switch (ltk->type) {
6234 case SMP_LTK:
6235 case SMP_LTK_SLAVE:
6236 if (ltk->authenticated)
6237 return MGMT_LTK_AUTHENTICATED;
6238 return MGMT_LTK_UNAUTHENTICATED;
6239 case SMP_LTK_P256:
6240 if (ltk->authenticated)
6241 return MGMT_LTK_P256_AUTH;
6242 return MGMT_LTK_P256_UNAUTH;
6243 case SMP_LTK_P256_DEBUG:
6244 return MGMT_LTK_P256_DEBUG;
6245 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006246
6247 return MGMT_LTK_UNAUTHENTICATED;
6248}
6249
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006250void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006251{
6252 struct mgmt_ev_new_long_term_key ev;
6253
6254 memset(&ev, 0, sizeof(ev));
6255
Marcel Holtmann5192d302014-02-19 17:11:58 -08006256 /* Devices using resolvable or non-resolvable random addresses
6257 * without providing an indentity resolving key don't require
6258 * to store long term keys. Their addresses will change the
6259 * next time around.
6260 *
6261 * Only when a remote device provides an identity address
6262 * make sure the long term key is stored. If the remote
6263 * identity is known, the long term keys are internally
6264 * mapped to the identity address. So allow static random
6265 * and public addresses here.
6266 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006267 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6268 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6269 ev.store_hint = 0x00;
6270 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006271 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006272
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006273 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006274 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006275 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006276 ev.key.enc_size = key->enc_size;
6277 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006278 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006279
Johan Hedberg2ceba532014-06-16 19:25:16 +03006280 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006281 ev.key.master = 1;
6282
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006283 memcpy(ev.key.val, key->val, sizeof(key->val));
6284
Marcel Holtmann083368f2013-10-15 14:26:29 -07006285 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006286}
6287
Johan Hedberg95fbac82014-02-19 15:18:31 +02006288void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6289{
6290 struct mgmt_ev_new_irk ev;
6291
6292 memset(&ev, 0, sizeof(ev));
6293
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006294 /* For identity resolving keys from devices that are already
6295 * using a public address or static random address, do not
6296 * ask for storing this key. The identity resolving key really
6297 * is only mandatory for devices using resovlable random
6298 * addresses.
6299 *
6300 * Storing all identity resolving keys has the downside that
6301 * they will be also loaded on next boot of they system. More
6302 * identity resolving keys, means more time during scanning is
6303 * needed to actually resolve these addresses.
6304 */
6305 if (bacmp(&irk->rpa, BDADDR_ANY))
6306 ev.store_hint = 0x01;
6307 else
6308 ev.store_hint = 0x00;
6309
Johan Hedberg95fbac82014-02-19 15:18:31 +02006310 bacpy(&ev.rpa, &irk->rpa);
6311 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6312 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6313 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6314
6315 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6316}
6317
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006318void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6319 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006320{
6321 struct mgmt_ev_new_csrk ev;
6322
6323 memset(&ev, 0, sizeof(ev));
6324
6325 /* Devices using resolvable or non-resolvable random addresses
6326 * without providing an indentity resolving key don't require
6327 * to store signature resolving keys. Their addresses will change
6328 * the next time around.
6329 *
6330 * Only when a remote device provides an identity address
6331 * make sure the signature resolving key is stored. So allow
6332 * static random and public addresses here.
6333 */
6334 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6335 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6336 ev.store_hint = 0x00;
6337 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006338 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006339
6340 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6341 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6342 ev.key.master = csrk->master;
6343 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6344
6345 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6346}
6347
Andre Guedesffb5a8272014-07-01 18:10:11 -03006348void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006349 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6350 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006351{
6352 struct mgmt_ev_new_conn_param ev;
6353
Johan Hedbergc103aea2014-07-02 17:37:34 +03006354 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6355 return;
6356
Andre Guedesffb5a8272014-07-01 18:10:11 -03006357 memset(&ev, 0, sizeof(ev));
6358 bacpy(&ev.addr.bdaddr, bdaddr);
6359 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006360 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006361 ev.min_interval = cpu_to_le16(min_interval);
6362 ev.max_interval = cpu_to_le16(max_interval);
6363 ev.latency = cpu_to_le16(latency);
6364 ev.timeout = cpu_to_le16(timeout);
6365
6366 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6367}
6368
Marcel Holtmann94933992013-10-15 10:26:39 -07006369static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6370 u8 data_len)
6371{
6372 eir[eir_len++] = sizeof(type) + data_len;
6373 eir[eir_len++] = type;
6374 memcpy(&eir[eir_len], data, data_len);
6375 eir_len += data_len;
6376
6377 return eir_len;
6378}
6379
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006380void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6381 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006382{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006383 char buf[512];
6384 struct mgmt_ev_device_connected *ev = (void *) buf;
6385 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006386
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006387 bacpy(&ev->addr.bdaddr, &conn->dst);
6388 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006389
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006390 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006391
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006392 /* We must ensure that the EIR Data fields are ordered and
6393 * unique. Keep it simple for now and avoid the problem by not
6394 * adding any BR/EDR data to the LE adv.
6395 */
6396 if (conn->le_adv_data_len > 0) {
6397 memcpy(&ev->eir[eir_len],
6398 conn->le_adv_data, conn->le_adv_data_len);
6399 eir_len = conn->le_adv_data_len;
6400 } else {
6401 if (name_len > 0)
6402 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6403 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006404
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006405 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006406 eir_len = eir_append_data(ev->eir, eir_len,
6407 EIR_CLASS_OF_DEV,
6408 conn->dev_class, 3);
6409 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006410
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006411 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006412
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006413 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6414 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006415}
6416
Johan Hedberg8962ee72011-01-20 12:40:27 +02006417static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6418{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006419 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006420
Johan Hedbergf5818c22014-12-05 13:36:02 +02006421 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006422
6423 *sk = cmd->sk;
6424 sock_hold(*sk);
6425
Johan Hedberga664b5b2011-02-19 12:06:02 -03006426 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006427}
6428
Johan Hedberg124f6e32012-02-09 13:50:12 +02006429static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006430{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006431 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006432 struct mgmt_cp_unpair_device *cp = cmd->param;
6433 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006434
6435 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02006436 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
6437 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006438
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006439 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6440
Johan Hedbergaee9b212012-02-18 15:07:59 +02006441 cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02006442
6443 mgmt_pending_remove(cmd);
6444}
6445
Johan Hedberg84c61d92014-08-01 11:13:30 +03006446bool mgmt_powering_down(struct hci_dev *hdev)
6447{
6448 struct pending_cmd *cmd;
6449 struct mgmt_mode *cp;
6450
6451 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6452 if (!cmd)
6453 return false;
6454
6455 cp = cmd->param;
6456 if (!cp->val)
6457 return true;
6458
6459 return false;
6460}
6461
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006462void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006463 u8 link_type, u8 addr_type, u8 reason,
6464 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006465{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006466 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006467 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006468
Johan Hedberg84c61d92014-08-01 11:13:30 +03006469 /* The connection is still in hci_conn_hash so test for 1
6470 * instead of 0 to know if this is the last one.
6471 */
6472 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6473 cancel_delayed_work(&hdev->power_off);
6474 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006475 }
6476
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006477 if (!mgmt_connected)
6478 return;
6479
Andre Guedes57eb7762013-10-30 19:01:41 -03006480 if (link_type != ACL_LINK && link_type != LE_LINK)
6481 return;
6482
Johan Hedberg744cf192011-11-08 20:40:14 +02006483 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006484
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006485 bacpy(&ev.addr.bdaddr, bdaddr);
6486 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6487 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006488
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006489 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006490
6491 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006492 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006493
Johan Hedberg124f6e32012-02-09 13:50:12 +02006494 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006495 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006496}
6497
Marcel Holtmann78929242013-10-06 23:55:47 -07006498void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6499 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006500{
Andre Guedes3655bba2013-10-30 19:01:40 -03006501 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6502 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006503 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006504
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006505 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6506 hdev);
6507
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006508 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006509 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006510 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006511
Andre Guedes3655bba2013-10-30 19:01:40 -03006512 cp = cmd->param;
6513
6514 if (bacmp(bdaddr, &cp->addr.bdaddr))
6515 return;
6516
6517 if (cp->addr.type != bdaddr_type)
6518 return;
6519
Johan Hedbergf5818c22014-12-05 13:36:02 +02006520 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006521 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006522}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006523
Marcel Holtmann445608d2013-10-06 23:55:48 -07006524void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6525 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006526{
6527 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006528
Johan Hedberg84c61d92014-08-01 11:13:30 +03006529 /* The connection is still in hci_conn_hash so test for 1
6530 * instead of 0 to know if this is the last one.
6531 */
6532 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6533 cancel_delayed_work(&hdev->power_off);
6534 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006535 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006536
Johan Hedberg4c659c32011-11-07 23:13:39 +02006537 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006538 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006539 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006540
Marcel Holtmann445608d2013-10-06 23:55:48 -07006541 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006542}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006543
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006544void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006545{
6546 struct mgmt_ev_pin_code_request ev;
6547
Johan Hedbergd8457692012-02-17 14:24:57 +02006548 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006549 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006550 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006551
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006552 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006553}
6554
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006555void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6556 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006557{
6558 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006559
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006560 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006561 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006562 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006563
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006564 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006565 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006566}
6567
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006568void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6569 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006570{
6571 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006572
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006573 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006574 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006575 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006576
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006577 cmd->cmd_complete(cmd, mgmt_status(status));
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;
Johan Hedberga5c29682011-02-19 12:05:57 -03006617
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006618 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006619 if (!cmd)
6620 return -ENOENT;
6621
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006622 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006623 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006624
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006625 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006626}
6627
Johan Hedberg744cf192011-11-08 20:40:14 +02006628int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006629 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006630{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006631 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006632 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006633}
6634
Johan Hedberg272d90d2012-02-09 15:26:12 +02006635int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006636 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006637{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006638 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006639 status,
6640 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006641}
Johan Hedberg2a611692011-02-19 12:06:00 -03006642
Brian Gix604086b2011-11-23 08:28:33 -08006643int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006644 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006645{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006646 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006647 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006648}
6649
Johan Hedberg272d90d2012-02-09 15:26:12 +02006650int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006651 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006652{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006653 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006654 status,
6655 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006656}
6657
Johan Hedberg92a25252012-09-06 18:39:26 +03006658int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6659 u8 link_type, u8 addr_type, u32 passkey,
6660 u8 entered)
6661{
6662 struct mgmt_ev_passkey_notify ev;
6663
6664 BT_DBG("%s", hdev->name);
6665
6666 bacpy(&ev.addr.bdaddr, bdaddr);
6667 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6668 ev.passkey = __cpu_to_le32(passkey);
6669 ev.entered = entered;
6670
6671 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6672}
6673
Johan Hedberge1e930f2014-09-08 17:09:49 -07006674void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006675{
6676 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006677 struct pending_cmd *cmd;
6678 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006679
Johan Hedberge1e930f2014-09-08 17:09:49 -07006680 bacpy(&ev.addr.bdaddr, &conn->dst);
6681 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6682 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006683
Johan Hedberge1e930f2014-09-08 17:09:49 -07006684 cmd = find_pairing(conn);
6685
6686 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6687 cmd ? cmd->sk : NULL);
6688
6689 if (cmd)
6690 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006691}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006692
Marcel Holtmann464996a2013-10-15 14:26:24 -07006693void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006694{
6695 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006696 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006697
6698 if (status) {
6699 u8 mgmt_err = mgmt_status(status);
6700 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006701 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006702 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006703 }
6704
Marcel Holtmann464996a2013-10-15 14:26:24 -07006705 if (test_bit(HCI_AUTH, &hdev->flags))
6706 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6707 &hdev->dev_flags);
6708 else
6709 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6710 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006711
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006712 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006713 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006714
Johan Hedberg47990ea2012-02-22 11:58:37 +02006715 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006716 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006717
6718 if (match.sk)
6719 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006720}
6721
Johan Hedberg890ea892013-03-15 17:06:52 -05006722static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006723{
Johan Hedberg890ea892013-03-15 17:06:52 -05006724 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006725 struct hci_cp_write_eir cp;
6726
Johan Hedberg976eb202012-10-24 21:12:01 +03006727 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006728 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006729
Johan Hedbergc80da272012-02-22 15:38:48 +02006730 memset(hdev->eir, 0, sizeof(hdev->eir));
6731
Johan Hedbergcacaf522012-02-21 00:52:42 +02006732 memset(&cp, 0, sizeof(cp));
6733
Johan Hedberg890ea892013-03-15 17:06:52 -05006734 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006735}
6736
Marcel Holtmann3e248562013-10-15 14:26:25 -07006737void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006738{
6739 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006740 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006741 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006742
6743 if (status) {
6744 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006745
6746 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006747 &hdev->dev_flags)) {
6748 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006749 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006750 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006751
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006752 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6753 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006754 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006755 }
6756
6757 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006758 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006759 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006760 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6761 if (!changed)
6762 changed = test_and_clear_bit(HCI_HS_ENABLED,
6763 &hdev->dev_flags);
6764 else
6765 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006766 }
6767
6768 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6769
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006770 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006771 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006772
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006773 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006774 sock_put(match.sk);
6775
Johan Hedberg890ea892013-03-15 17:06:52 -05006776 hci_req_init(&req, hdev);
6777
Johan Hedberg37699722014-06-24 14:00:27 +03006778 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6779 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6780 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6781 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006782 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006783 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006784 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006785 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006786
6787 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006788}
6789
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006790void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6791{
6792 struct cmd_lookup match = { NULL, hdev };
6793 bool changed = false;
6794
6795 if (status) {
6796 u8 mgmt_err = mgmt_status(status);
6797
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006798 if (enable) {
6799 if (test_and_clear_bit(HCI_SC_ENABLED,
6800 &hdev->dev_flags))
6801 new_settings(hdev, NULL);
6802 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6803 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006804
6805 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6806 cmd_status_rsp, &mgmt_err);
6807 return;
6808 }
6809
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006810 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006811 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006812 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006813 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006814 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6815 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006816
6817 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6818 settings_rsp, &match);
6819
6820 if (changed)
6821 new_settings(hdev, match.sk);
6822
6823 if (match.sk)
6824 sock_put(match.sk);
6825}
6826
Johan Hedberg92da6092013-03-15 17:06:55 -05006827static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006828{
6829 struct cmd_lookup *match = data;
6830
Johan Hedberg90e70452012-02-23 23:09:40 +02006831 if (match->sk == NULL) {
6832 match->sk = cmd->sk;
6833 sock_hold(match->sk);
6834 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006835}
6836
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006837void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6838 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006839{
Johan Hedberg90e70452012-02-23 23:09:40 +02006840 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006841
Johan Hedberg92da6092013-03-15 17:06:55 -05006842 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6843 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6844 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006845
6846 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006847 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6848 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006849
6850 if (match.sk)
6851 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006852}
6853
Marcel Holtmann7667da32013-10-15 14:26:27 -07006854void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006855{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006856 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006857 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006858
Johan Hedberg13928972013-03-15 17:07:00 -05006859 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006860 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006861
6862 memset(&ev, 0, sizeof(ev));
6863 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006864 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006865
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006866 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006867 if (!cmd) {
6868 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006869
Johan Hedberg13928972013-03-15 17:07:00 -05006870 /* If this is a HCI command related to powering on the
6871 * HCI dev don't send any mgmt signals.
6872 */
6873 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006874 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006875 }
6876
Marcel Holtmann7667da32013-10-15 14:26:27 -07006877 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6878 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006879}
Szymon Jancc35938b2011-03-22 13:12:21 +01006880
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006881void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006882 u8 *rand192, u8 *hash256, u8 *rand256,
6883 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006884{
6885 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006886
Johan Hedberg744cf192011-11-08 20:40:14 +02006887 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006888
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006889 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006890 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006891 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006892
6893 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006894 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6895 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006896 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006897 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006898 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006899
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006900 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006901 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006902
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006903 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006904 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006905
6906 cmd_complete(cmd->sk, hdev->id,
6907 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6908 &rp, sizeof(rp));
6909 } else {
6910 struct mgmt_rp_read_local_oob_data rp;
6911
6912 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006913 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006914
6915 cmd_complete(cmd->sk, hdev->id,
6916 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6917 &rp, sizeof(rp));
6918 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006919 }
6920
6921 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006922}
Johan Hedberge17acd42011-03-30 23:57:16 +03006923
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006924/* this is reversed hex representation of bluetooth base uuid. We need it for
6925 * service uuid parsing in eir.
6926 */
6927static const u8 reverse_base_uuid[] = {
6928 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6929 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6930};
6931
6932static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6933{
6934 int i;
6935
6936 for (i = 0; i < uuid_count; i++) {
6937 if (!memcmp(uuid, uuids[i], 16))
6938 return true;
6939 }
6940
6941 return false;
6942}
6943
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006944static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6945{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006946 u16 parsed = 0;
6947
6948 while (parsed < eir_len) {
6949 u8 field_len = eir[0];
6950 u8 uuid[16];
6951 int i;
6952
6953 if (field_len == 0)
6954 break;
6955
6956 if (eir_len - parsed < field_len + 1)
6957 break;
6958
6959 switch (eir[1]) {
6960 case EIR_UUID16_ALL:
6961 case EIR_UUID16_SOME:
6962 for (i = 0; i + 3 <= field_len; i += 2) {
6963 memcpy(uuid, reverse_base_uuid, 16);
6964 uuid[13] = eir[i + 3];
6965 uuid[12] = eir[i + 2];
6966 if (has_uuid(uuid, uuid_count, uuids))
6967 return true;
6968 }
6969 break;
6970 case EIR_UUID32_ALL:
6971 case EIR_UUID32_SOME:
6972 for (i = 0; i + 5 <= field_len; i += 4) {
6973 memcpy(uuid, reverse_base_uuid, 16);
6974 uuid[15] = eir[i + 5];
6975 uuid[14] = eir[i + 4];
6976 uuid[13] = eir[i + 3];
6977 uuid[12] = eir[i + 2];
6978 if (has_uuid(uuid, uuid_count, uuids))
6979 return true;
6980 }
6981 break;
6982 case EIR_UUID128_ALL:
6983 case EIR_UUID128_SOME:
6984 for (i = 0; i + 17 <= field_len; i += 16) {
6985 memcpy(uuid, eir + i + 2, 16);
6986 if (has_uuid(uuid, uuid_count, uuids))
6987 return true;
6988 }
6989 break;
6990 }
6991
6992 parsed += field_len + 1;
6993 eir += field_len + 1;
6994 }
6995
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006996 return false;
6997}
6998
Marcel Holtmann901801b2013-10-06 23:55:51 -07006999void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007000 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7001 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007002{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007003 char buf[512];
7004 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007005 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007006 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007007
Johan Hedberg75ce2082014-07-02 22:42:01 +03007008 /* Don't send events for a non-kernel initiated discovery. With
7009 * LE one exception is if we have pend_le_reports > 0 in which
7010 * case we're doing passive scanning and want these events.
7011 */
7012 if (!hci_discovery_active(hdev)) {
7013 if (link_type == ACL_LINK)
7014 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007015 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007016 return;
7017 }
Andre Guedes12602d02013-04-30 15:29:40 -03007018
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007019 /* When using service discovery with a RSSI threshold, then check
7020 * if such a RSSI threshold is specified. If a RSSI threshold has
7021 * been specified, then all results with a RSSI smaller than the
7022 * RSSI threshold will be dropped.
7023 */
7024 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7025 rssi < hdev->discovery.rssi)
7026 return;
7027
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007028 /* Make sure that the buffer is big enough. The 5 extra bytes
7029 * are for the potential CoD field.
7030 */
7031 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007032 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007033
Johan Hedberg1dc06092012-01-15 21:01:23 +02007034 memset(buf, 0, sizeof(buf));
7035
Johan Hedberg841c5642014-07-07 12:45:54 +03007036 bacpy(&ev->addr.bdaddr, bdaddr);
7037 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007038 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007039 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007040
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007041 if (eir_len > 0) {
7042 /* When using service discovery and a list of UUID is
7043 * provided, results with no matching UUID should be
7044 * dropped. In case there is a match the result is
7045 * kept and checking possible scan response data
7046 * will be skipped.
7047 */
7048 if (hdev->discovery.uuid_count > 0) {
7049 match = eir_has_uuids(eir, eir_len,
7050 hdev->discovery.uuid_count,
7051 hdev->discovery.uuids);
7052 if (!match)
7053 return;
7054 }
7055
7056 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007057 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007058 } else {
7059 /* When using service discovery and a list of UUID is
7060 * provided, results with empty EIR or advertising data
7061 * should be dropped since they do not match any UUID.
7062 */
7063 if (hdev->discovery.uuid_count > 0)
7064 return;
7065 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007066
Johan Hedberg1dc06092012-01-15 21:01:23 +02007067 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7068 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007069 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007070
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007071 if (scan_rsp_len > 0) {
7072 /* When using service discovery and a list of UUID is
7073 * provided, results with no matching UUID should be
7074 * dropped if there is no previous match from the
7075 * advertising data.
7076 */
7077 if (hdev->discovery.uuid_count > 0) {
7078 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7079 hdev->discovery.uuid_count,
7080 hdev->discovery.uuids))
7081 return;
7082 }
7083
7084 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007085 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007086 } else {
7087 /* When using service discovery and a list of UUID is
7088 * provided, results with empty scan response and no
7089 * previous matched advertising data should be dropped.
7090 */
7091 if (hdev->discovery.uuid_count > 0 && !match)
7092 return;
7093 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007094
7095 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7096 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007097
Marcel Holtmann901801b2013-10-06 23:55:51 -07007098 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007099}
Johan Hedberga88a9652011-03-30 13:18:12 +03007100
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007101void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7102 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007103{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007104 struct mgmt_ev_device_found *ev;
7105 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7106 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007107
Johan Hedbergb644ba32012-01-17 21:48:47 +02007108 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007109
Johan Hedbergb644ba32012-01-17 21:48:47 +02007110 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007111
Johan Hedbergb644ba32012-01-17 21:48:47 +02007112 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007113 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007114 ev->rssi = rssi;
7115
7116 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007117 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007118
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007119 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007120
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007121 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007122}
Johan Hedberg314b2382011-04-27 10:29:57 -04007123
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007124void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007125{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007126 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007127
Andre Guedes343fb142011-11-22 17:14:19 -03007128 BT_DBG("%s discovering %u", hdev->name, discovering);
7129
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007130 memset(&ev, 0, sizeof(ev));
7131 ev.type = hdev->discovery.type;
7132 ev.discovering = discovering;
7133
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007134 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007135}
Antti Julku5e762442011-08-25 16:48:02 +03007136
Marcel Holtmann5976e602013-10-06 04:08:14 -07007137static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7138{
7139 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007140}
7141
7142void mgmt_reenable_advertising(struct hci_dev *hdev)
7143{
7144 struct hci_request req;
7145
Marcel Holtmann5976e602013-10-06 04:08:14 -07007146 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7147 return;
7148
7149 hci_req_init(&req, hdev);
7150 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007151 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007152}