blob: 34da65ccc888d7bfc5d6c3b2ecae76c4fc3614ff [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200138 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200141 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300556 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac142014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300580 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200581 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300582 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200583
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200584 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
585 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586 settings |= MGMT_SETTING_CONFIGURATION;
587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588 return settings;
589}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_current_settings(struct hci_dev *hdev)
592{
593 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200594
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200595 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100596 settings |= MGMT_SETTING_POWERED;
597
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200598 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200599 settings |= MGMT_SETTING_CONNECTABLE;
600
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500601 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
602 settings |= MGMT_SETTING_FAST_CONNECTABLE;
603
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200604 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605 settings |= MGMT_SETTING_DISCOVERABLE;
606
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300607 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300608 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609
Johan Hedberg56f87902013-10-02 13:43:13 +0300610 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_BREDR;
612
Johan Hedberg06199cf2012-02-22 16:37:11 +0200613 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200615
Johan Hedberg47990ea2012-02-22 11:58:37 +0200616 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200618
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200621
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200622 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
623 settings |= MGMT_SETTING_HS;
624
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200625 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300626 settings |= MGMT_SETTING_ADVERTISING;
627
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800628 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
629 settings |= MGMT_SETTING_SECURE_CONN;
630
Johan Hedberg0663b292014-06-24 13:15:50 +0300631 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800632 settings |= MGMT_SETTING_DEBUG_KEYS;
633
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
635 settings |= MGMT_SETTING_PRIVACY;
636
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200637 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200638}
639
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300640#define PNP_INFO_SVCLASS_ID 0x1200
641
Johan Hedberg213202e2013-01-27 00:31:33 +0200642static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
643{
644 u8 *ptr = data, *uuids_start = NULL;
645 struct bt_uuid *uuid;
646
647 if (len < 4)
648 return ptr;
649
650 list_for_each_entry(uuid, &hdev->uuids, list) {
651 u16 uuid16;
652
653 if (uuid->size != 16)
654 continue;
655
656 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
657 if (uuid16 < 0x1100)
658 continue;
659
660 if (uuid16 == PNP_INFO_SVCLASS_ID)
661 continue;
662
663 if (!uuids_start) {
664 uuids_start = ptr;
665 uuids_start[0] = 1;
666 uuids_start[1] = EIR_UUID16_ALL;
667 ptr += 2;
668 }
669
670 /* Stop if not enough space to put next UUID */
671 if ((ptr - data) + sizeof(u16) > len) {
672 uuids_start[1] = EIR_UUID16_SOME;
673 break;
674 }
675
676 *ptr++ = (uuid16 & 0x00ff);
677 *ptr++ = (uuid16 & 0xff00) >> 8;
678 uuids_start[0] += sizeof(uuid16);
679 }
680
681 return ptr;
682}
683
Johan Hedbergcdf19632013-01-27 00:31:34 +0200684static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
685{
686 u8 *ptr = data, *uuids_start = NULL;
687 struct bt_uuid *uuid;
688
689 if (len < 6)
690 return ptr;
691
692 list_for_each_entry(uuid, &hdev->uuids, list) {
693 if (uuid->size != 32)
694 continue;
695
696 if (!uuids_start) {
697 uuids_start = ptr;
698 uuids_start[0] = 1;
699 uuids_start[1] = EIR_UUID32_ALL;
700 ptr += 2;
701 }
702
703 /* Stop if not enough space to put next UUID */
704 if ((ptr - data) + sizeof(u32) > len) {
705 uuids_start[1] = EIR_UUID32_SOME;
706 break;
707 }
708
709 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
710 ptr += sizeof(u32);
711 uuids_start[0] += sizeof(u32);
712 }
713
714 return ptr;
715}
716
Johan Hedbergc00d5752013-01-27 00:31:35 +0200717static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
718{
719 u8 *ptr = data, *uuids_start = NULL;
720 struct bt_uuid *uuid;
721
722 if (len < 18)
723 return ptr;
724
725 list_for_each_entry(uuid, &hdev->uuids, list) {
726 if (uuid->size != 128)
727 continue;
728
729 if (!uuids_start) {
730 uuids_start = ptr;
731 uuids_start[0] = 1;
732 uuids_start[1] = EIR_UUID128_ALL;
733 ptr += 2;
734 }
735
736 /* Stop if not enough space to put next UUID */
737 if ((ptr - data) + 16 > len) {
738 uuids_start[1] = EIR_UUID128_SOME;
739 break;
740 }
741
742 memcpy(ptr, uuid->uuid, 16);
743 ptr += 16;
744 uuids_start[0] += 16;
745 }
746
747 return ptr;
748}
749
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300750static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
751{
752 struct pending_cmd *cmd;
753
754 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
755 if (cmd->opcode == opcode)
756 return cmd;
757 }
758
759 return NULL;
760}
761
Johan Hedberg95868422014-06-28 17:54:07 +0300762static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
763 struct hci_dev *hdev,
764 const void *data)
765{
766 struct pending_cmd *cmd;
767
768 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
769 if (cmd->user_data != data)
770 continue;
771 if (cmd->opcode == opcode)
772 return cmd;
773 }
774
775 return NULL;
776}
777
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700778static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
779{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700780 u8 ad_len = 0;
781 size_t name_len;
782
783 name_len = strlen(hdev->dev_name);
784 if (name_len > 0) {
785 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
786
787 if (name_len > max_len) {
788 name_len = max_len;
789 ptr[1] = EIR_NAME_SHORT;
790 } else
791 ptr[1] = EIR_NAME_COMPLETE;
792
793 ptr[0] = name_len + 1;
794
795 memcpy(ptr + 2, hdev->dev_name, name_len);
796
797 ad_len += (name_len + 2);
798 ptr += (name_len + 2);
799 }
800
801 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802}
803
804static void update_scan_rsp_data(struct hci_request *req)
805{
806 struct hci_dev *hdev = req->hdev;
807 struct hci_cp_le_set_scan_rsp_data cp;
808 u8 len;
809
Johan Hedberg7751ef12013-10-19 23:38:15 +0300810 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811 return;
812
813 memset(&cp, 0, sizeof(cp));
814
815 len = create_scan_rsp_data(hdev, cp.data);
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 if (hdev->scan_rsp_data_len == len &&
818 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819 return;
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
822 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823
824 cp.length = len;
825
826 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
827}
828
Johan Hedberg9a43e252013-10-20 19:00:07 +0300829static u8 get_adv_discov_flags(struct hci_dev *hdev)
830{
831 struct pending_cmd *cmd;
832
833 /* If there's a pending mgmt command the flags will not yet have
834 * their final values, so check for this first.
835 */
836 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
837 if (cmd) {
838 struct mgmt_mode *cp = cmd->param;
839 if (cp->val == 0x01)
840 return LE_AD_GENERAL;
841 else if (cp->val == 0x02)
842 return LE_AD_LIMITED;
843 } else {
844 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_LIMITED;
846 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
847 return LE_AD_GENERAL;
848 }
849
850 return 0;
851}
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854{
855 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberg9a43e252013-10-20 19:00:07 +0300857 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
Johan Hedberge8340042014-01-30 11:16:50 -0800859 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
862 if (flags) {
863 BT_DBG("adv flags 0x%02x", flags);
864
865 ptr[0] = 2;
866 ptr[1] = EIR_FLAGS;
867 ptr[2] = flags;
868
869 ad_len += 3;
870 ptr += 3;
871 }
872
873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
874 ptr[0] = 2;
875 ptr[1] = EIR_TX_POWER;
876 ptr[2] = (u8) hdev->adv_tx_power;
877
878 ad_len += 3;
879 ptr += 3;
880 }
881
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882 return ad_len;
883}
884
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700885static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886{
887 struct hci_dev *hdev = req->hdev;
888 struct hci_cp_le_set_adv_data cp;
889 u8 len;
890
Johan Hedberg10994ce2013-10-19 23:38:16 +0300891 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700892 return;
893
894 memset(&cp, 0, sizeof(cp));
895
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700896 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700897
898 if (hdev->adv_data_len == len &&
899 memcmp(cp.data, hdev->adv_data, len) == 0)
900 return;
901
902 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
903 hdev->adv_data_len = len;
904
905 cp.length = len;
906
907 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
908}
909
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300910int mgmt_update_adv_data(struct hci_dev *hdev)
911{
912 struct hci_request req;
913
914 hci_req_init(&req, hdev);
915 update_adv_data(&req);
916
917 return hci_req_run(&req, NULL);
918}
919
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920static void create_eir(struct hci_dev *hdev, u8 *data)
921{
922 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923 size_t name_len;
924
925 name_len = strlen(hdev->dev_name);
926
927 if (name_len > 0) {
928 /* EIR Data type */
929 if (name_len > 48) {
930 name_len = 48;
931 ptr[1] = EIR_NAME_SHORT;
932 } else
933 ptr[1] = EIR_NAME_COMPLETE;
934
935 /* EIR Data length */
936 ptr[0] = name_len + 1;
937
938 memcpy(ptr + 2, hdev->dev_name, name_len);
939
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300940 ptr += (name_len + 2);
941 }
942
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100943 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr[0] = 2;
945 ptr[1] = EIR_TX_POWER;
946 ptr[2] = (u8) hdev->inq_tx_power;
947
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr += 3;
949 }
950
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700951 if (hdev->devid_source > 0) {
952 ptr[0] = 9;
953 ptr[1] = EIR_DEVICE_ID;
954
955 put_unaligned_le16(hdev->devid_source, ptr + 2);
956 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
957 put_unaligned_le16(hdev->devid_product, ptr + 6);
958 put_unaligned_le16(hdev->devid_version, ptr + 8);
959
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700960 ptr += 10;
961 }
962
Johan Hedberg213202e2013-01-27 00:31:33 +0200963 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200964 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200965 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966}
967
Johan Hedberg890ea892013-03-15 17:06:52 -0500968static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969{
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300971 struct hci_cp_write_eir cp;
972
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200973 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200975
Johan Hedberg976eb202012-10-24 21:12:01 +0300976 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200979 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200982 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
985 memset(&cp, 0, sizeof(cp));
986
987 create_eir(hdev, cp.data);
988
989 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991
992 memcpy(hdev->eir, cp.data, sizeof(cp.data));
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995}
996
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997static u8 get_service_classes(struct hci_dev *hdev)
998{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 val = 0;
1001
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004
1005 return val;
1006}
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009{
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001011 u8 cod[3];
1012
1013 BT_DBG("%s", hdev->name);
1014
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001015 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001017
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001018 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1019 return;
1020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001021 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001022 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
1024 cod[0] = hdev->minor_class;
1025 cod[1] = hdev->major_class;
1026 cod[2] = get_service_classes(hdev);
1027
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001028 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1029 cod[1] |= 0x20;
1030
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035}
1036
Johan Hedberga4858cb2014-02-25 19:56:31 +02001037static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038{
1039 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040
1041 /* If there's a pending mgmt command the flag will not yet have
1042 * it's final value, so check for this first.
1043 */
1044 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1045 if (cmd) {
1046 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048 }
1049
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051}
1052
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001053static void disable_advertising(struct hci_request *req)
1054{
1055 u8 enable = 0x00;
1056
1057 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1058}
1059
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001060static void enable_advertising(struct hci_request *req)
1061{
1062 struct hci_dev *hdev = req->hdev;
1063 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001064 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001066
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001067 if (hci_conn_num(hdev, LE_LINK) > 0)
1068 return;
1069
1070 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1071 disable_advertising(req);
1072
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001073 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001074 * hci_update_random_address knows that it's safe to go ahead
1075 * and write a new random address. The flag will be set back on
1076 * as soon as the SET_ADV_ENABLE HCI command completes.
1077 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001078 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001081
Johan Hedberga4858cb2014-02-25 19:56:31 +02001082 /* Set require_privacy to true only when non-connectable
1083 * advertising is used. In that case it is fine to use a
1084 * non-resolvable private address.
1085 */
1086 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001087 return;
1088
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001089 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001090 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1091 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001092 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001093 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001094 cp.channel_map = hdev->le_adv_channel_map;
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1097
1098 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1099}
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101static void service_cache_off(struct work_struct *work)
1102{
1103 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001104 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001107 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 return;
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 hci_req_init(&req, hdev);
1111
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 hci_dev_lock(hdev);
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 update_eir(&req);
1115 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116
1117 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001118
1119 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120}
1121
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122static void rpa_expired(struct work_struct *work)
1123{
1124 struct hci_dev *hdev = container_of(work, struct hci_dev,
1125 rpa_expired.work);
1126 struct hci_request req;
1127
1128 BT_DBG("");
1129
1130 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1131
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001132 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001133 return;
1134
1135 /* The generation of a new RPA and programming it into the
1136 * controller happens in the enable_advertising() function.
1137 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 hci_req_run(&req, NULL);
1141}
1142
Johan Hedberg6a919082012-02-28 06:17:26 +02001143static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001144{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001146 return;
1147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001149 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 /* Non-mgmt controlled devices get this bit set
1152 * implicitly so that pairing works for them, however
1153 * for mgmt we require user-space to explicitly enable
1154 * it
1155 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001156 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001157}
1158
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001159static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001161{
1162 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 memset(&rp, 0, sizeof(rp));
1169
Johan Hedberg03811012010-12-08 00:21:06 +02001170 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001173 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1176 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1177
1178 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
1180 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001181 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001183 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001184
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001185 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001187}
1188
1189static void mgmt_pending_free(struct pending_cmd *cmd)
1190{
1191 sock_put(cmd->sk);
1192 kfree(cmd->param);
1193 kfree(cmd);
1194}
1195
1196static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 struct hci_dev *hdev, void *data,
1198 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001199{
1200 struct pending_cmd *cmd;
1201
Johan Hedbergfca20012014-06-28 17:54:05 +03001202 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 if (!cmd)
1204 return NULL;
1205
1206 cmd->opcode = opcode;
1207 cmd->index = hdev->id;
1208
Johan Hedberg323b0b82014-12-05 13:36:01 +02001209 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001210 if (!cmd->param) {
1211 kfree(cmd);
1212 return NULL;
1213 }
1214
Johan Hedberg323b0b82014-12-05 13:36:01 +02001215 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b2182012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedbergf5818c22014-12-05 13:36:02 +02001489static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
1490{
1491 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1492 cmd->param_len);
1493}
1494
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001495static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1496{
1497 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
1499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001569 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001816 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001850 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302202 hci_dev_lock(hdev);
2203
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002204 if (status) {
2205 u8 mgmt_err = mgmt_status(status);
2206
2207 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2208 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302209 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002210 }
2211
2212 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2213
2214 new_settings(hdev, match.sk);
2215
2216 if (match.sk)
2217 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002218
2219 /* Make sure the controller has a good default for
2220 * advertising data. Restrict the update to when LE
2221 * has actually been enabled. During power on, the
2222 * update in powered_update_hci will take care of it.
2223 */
2224 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2225 struct hci_request req;
2226
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
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);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002233 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302234
2235unlock:
2236 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002237}
2238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002239static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002240{
2241 struct mgmt_mode *cp = data;
2242 struct hci_cp_write_le_host_supported hci_cp;
2243 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002244 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002245 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002246 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002247
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002248 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002249
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002250 if (!lmp_le_capable(hdev))
2251 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2252 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002253
Johan Hedberga7e80f22013-01-09 16:05:19 +02002254 if (cp->val != 0x00 && cp->val != 0x01)
2255 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2256 MGMT_STATUS_INVALID_PARAMS);
2257
Johan Hedbergc73eee92013-04-19 18:35:21 +03002258 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002259 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002260 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2261 MGMT_STATUS_REJECTED);
2262
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002263 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002264
2265 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002266 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002267
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002268 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002269 bool changed = false;
2270
2271 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2272 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2273 changed = true;
2274 }
2275
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002276 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2277 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002278 changed = true;
2279 }
2280
Johan Hedberg06199cf2012-02-22 16:37:11 +02002281 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2282 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002283 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002284
2285 if (changed)
2286 err = new_settings(hdev, sk);
2287
Johan Hedberg1de028c2012-02-29 19:55:35 -08002288 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002289 }
2290
Johan Hedberg4375f102013-09-25 13:26:10 +03002291 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2292 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002293 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002294 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002295 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002296 }
2297
2298 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2299 if (!cmd) {
2300 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002301 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002302 }
2303
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002304 hci_req_init(&req, hdev);
2305
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306 memset(&hci_cp, 0, sizeof(hci_cp));
2307
2308 if (val) {
2309 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002310 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002311 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002312 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002313 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002314 }
2315
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002316 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2317 &hci_cp);
2318
2319 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302320 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002322
Johan Hedberg1de028c2012-02-29 19:55:35 -08002323unlock:
2324 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002325 return err;
2326}
2327
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002328/* This is a helper function to test for pending mgmt commands that can
2329 * cause CoD or EIR HCI commands. We can only allow one such pending
2330 * mgmt command at a time since otherwise we cannot easily track what
2331 * the current values are, will be, and based on that calculate if a new
2332 * HCI command needs to be sent and if yes with what value.
2333 */
2334static bool pending_eir_or_class(struct hci_dev *hdev)
2335{
2336 struct pending_cmd *cmd;
2337
2338 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2339 switch (cmd->opcode) {
2340 case MGMT_OP_ADD_UUID:
2341 case MGMT_OP_REMOVE_UUID:
2342 case MGMT_OP_SET_DEV_CLASS:
2343 case MGMT_OP_SET_POWERED:
2344 return true;
2345 }
2346 }
2347
2348 return false;
2349}
2350
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002351static const u8 bluetooth_base_uuid[] = {
2352 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2353 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2354};
2355
2356static u8 get_uuid_size(const u8 *uuid)
2357{
2358 u32 val;
2359
2360 if (memcmp(uuid, bluetooth_base_uuid, 12))
2361 return 128;
2362
2363 val = get_unaligned_le32(&uuid[12]);
2364 if (val > 0xffff)
2365 return 32;
2366
2367 return 16;
2368}
2369
Johan Hedberg92da6092013-03-15 17:06:55 -05002370static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2371{
2372 struct pending_cmd *cmd;
2373
2374 hci_dev_lock(hdev);
2375
2376 cmd = mgmt_pending_find(mgmt_op, hdev);
2377 if (!cmd)
2378 goto unlock;
2379
2380 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2381 hdev->dev_class, 3);
2382
2383 mgmt_pending_remove(cmd);
2384
2385unlock:
2386 hci_dev_unlock(hdev);
2387}
2388
2389static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2390{
2391 BT_DBG("status 0x%02x", status);
2392
2393 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2394}
2395
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002396static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002397{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002398 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002399 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002400 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002402 int err;
2403
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002404 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002405
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002406 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002407
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002408 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002409 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002410 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002411 goto failed;
2412 }
2413
Andre Guedes92c4c202012-06-07 19:05:44 -03002414 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002415 if (!uuid) {
2416 err = -ENOMEM;
2417 goto failed;
2418 }
2419
2420 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002421 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002422 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002423
Johan Hedbergde66aa62013-01-27 00:31:27 +02002424 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002425
Johan Hedberg890ea892013-03-15 17:06:52 -05002426 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002427
Johan Hedberg890ea892013-03-15 17:06:52 -05002428 update_class(&req);
2429 update_eir(&req);
2430
Johan Hedberg92da6092013-03-15 17:06:55 -05002431 err = hci_req_run(&req, add_uuid_complete);
2432 if (err < 0) {
2433 if (err != -ENODATA)
2434 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002435
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002436 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002437 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002438 goto failed;
2439 }
2440
2441 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002442 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002443 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002444 goto failed;
2445 }
2446
2447 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002448
2449failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002450 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002451 return err;
2452}
2453
Johan Hedberg24b78d02012-02-23 23:24:30 +02002454static bool enable_service_cache(struct hci_dev *hdev)
2455{
2456 if (!hdev_is_powered(hdev))
2457 return false;
2458
2459 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002460 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2461 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002462 return true;
2463 }
2464
2465 return false;
2466}
2467
Johan Hedberg92da6092013-03-15 17:06:55 -05002468static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2469{
2470 BT_DBG("status 0x%02x", status);
2471
2472 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2473}
2474
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002475static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002476 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002477{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002478 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002479 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002480 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002481 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 -05002482 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002483 int err, found;
2484
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002485 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002486
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002487 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002488
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002489 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002490 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002491 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002492 goto unlock;
2493 }
2494
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002495 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002496 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002497
Johan Hedberg24b78d02012-02-23 23:24:30 +02002498 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002499 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002500 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002501 goto unlock;
2502 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002503
Johan Hedberg9246a862012-02-23 21:33:16 +02002504 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002505 }
2506
2507 found = 0;
2508
Johan Hedberg056341c2013-01-27 00:31:30 +02002509 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002510 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2511 continue;
2512
2513 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002514 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002515 found++;
2516 }
2517
2518 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002519 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002520 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002521 goto unlock;
2522 }
2523
Johan Hedberg9246a862012-02-23 21:33:16 +02002524update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002525 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002526
Johan Hedberg890ea892013-03-15 17:06:52 -05002527 update_class(&req);
2528 update_eir(&req);
2529
Johan Hedberg92da6092013-03-15 17:06:55 -05002530 err = hci_req_run(&req, remove_uuid_complete);
2531 if (err < 0) {
2532 if (err != -ENODATA)
2533 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002534
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002535 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002536 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002537 goto unlock;
2538 }
2539
2540 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002541 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002542 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002543 goto unlock;
2544 }
2545
2546 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002547
2548unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002549 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002550 return err;
2551}
2552
Johan Hedberg92da6092013-03-15 17:06:55 -05002553static void set_class_complete(struct hci_dev *hdev, u8 status)
2554{
2555 BT_DBG("status 0x%02x", status);
2556
2557 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2558}
2559
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002560static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002561 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002562{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002563 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002564 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002565 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002566 int err;
2567
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002568 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002569
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002570 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002571 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2572 MGMT_STATUS_NOT_SUPPORTED);
2573
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002574 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002575
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002576 if (pending_eir_or_class(hdev)) {
2577 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2578 MGMT_STATUS_BUSY);
2579 goto unlock;
2580 }
2581
2582 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2583 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2584 MGMT_STATUS_INVALID_PARAMS);
2585 goto unlock;
2586 }
2587
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002588 hdev->major_class = cp->major;
2589 hdev->minor_class = cp->minor;
2590
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002591 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002592 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002593 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002594 goto unlock;
2595 }
2596
Johan Hedberg890ea892013-03-15 17:06:52 -05002597 hci_req_init(&req, hdev);
2598
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002599 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002600 hci_dev_unlock(hdev);
2601 cancel_delayed_work_sync(&hdev->service_cache);
2602 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002603 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002604 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002605
Johan Hedberg890ea892013-03-15 17:06:52 -05002606 update_class(&req);
2607
Johan Hedberg92da6092013-03-15 17:06:55 -05002608 err = hci_req_run(&req, set_class_complete);
2609 if (err < 0) {
2610 if (err != -ENODATA)
2611 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002612
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002613 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002614 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002615 goto unlock;
2616 }
2617
2618 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002619 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002620 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002621 goto unlock;
2622 }
2623
2624 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002625
Johan Hedbergb5235a62012-02-21 14:32:24 +02002626unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002627 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002628 return err;
2629}
2630
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002631static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002632 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002633{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002634 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002635 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2636 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002637 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002638 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002639 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002640
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002641 BT_DBG("request for %s", hdev->name);
2642
2643 if (!lmp_bredr_capable(hdev))
2644 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2645 MGMT_STATUS_NOT_SUPPORTED);
2646
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002647 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002648 if (key_count > max_key_count) {
2649 BT_ERR("load_link_keys: too big key_count value %u",
2650 key_count);
2651 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2652 MGMT_STATUS_INVALID_PARAMS);
2653 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002654
Johan Hedberg86742e12011-11-07 23:13:38 +02002655 expected_len = sizeof(*cp) + key_count *
2656 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002657 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002658 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002659 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002660 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002661 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002662 }
2663
Johan Hedberg4ae14302013-01-20 14:27:13 +02002664 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2665 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2666 MGMT_STATUS_INVALID_PARAMS);
2667
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002668 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002669 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002670
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002671 for (i = 0; i < key_count; i++) {
2672 struct mgmt_link_key_info *key = &cp->keys[i];
2673
Marcel Holtmann8e991132014-01-10 02:07:25 -08002674 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002675 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2676 MGMT_STATUS_INVALID_PARAMS);
2677 }
2678
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002679 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002680
2681 hci_link_keys_clear(hdev);
2682
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002683 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002684 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2685 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002686 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002687 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2688 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002689
2690 if (changed)
2691 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002692
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002693 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002694 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002695
Johan Hedberg58e92932014-06-24 14:00:26 +03002696 /* Always ignore debug keys and require a new pairing if
2697 * the user wants to use them.
2698 */
2699 if (key->type == HCI_LK_DEBUG_COMBINATION)
2700 continue;
2701
Johan Hedberg7652ff62014-06-24 13:15:49 +03002702 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2703 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002704 }
2705
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002706 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002707
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002708 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002709
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002710 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002711}
2712
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002713static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002714 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002715{
2716 struct mgmt_ev_device_unpaired ev;
2717
2718 bacpy(&ev.addr.bdaddr, bdaddr);
2719 ev.addr.type = addr_type;
2720
2721 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002722 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002723}
2724
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002725static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002726 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002727{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002728 struct mgmt_cp_unpair_device *cp = data;
2729 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002730 struct hci_cp_disconnect dc;
2731 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002733 int err;
2734
Johan Hedberga8a1d192011-11-10 15:54:38 +02002735 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002736 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2737 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002738
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002739 if (!bdaddr_type_is_valid(cp->addr.type))
2740 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2741 MGMT_STATUS_INVALID_PARAMS,
2742 &rp, sizeof(rp));
2743
Johan Hedberg118da702013-01-20 14:27:20 +02002744 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2745 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2746 MGMT_STATUS_INVALID_PARAMS,
2747 &rp, sizeof(rp));
2748
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002749 hci_dev_lock(hdev);
2750
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002751 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002752 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002753 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002754 goto unlock;
2755 }
2756
Johan Hedberge0b2b272014-02-18 17:14:31 +02002757 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002758 /* If disconnection is requested, then look up the
2759 * connection. If the remote device is connected, it
2760 * will be later used to terminate the link.
2761 *
2762 * Setting it to NULL explicitly will cause no
2763 * termination of the link.
2764 */
2765 if (cp->disconnect)
2766 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2767 &cp->addr.bdaddr);
2768 else
2769 conn = NULL;
2770
Johan Hedberg124f6e32012-02-09 13:50:12 +02002771 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002772 } else {
2773 u8 addr_type;
2774
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002775 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2776 &cp->addr.bdaddr);
2777 if (conn) {
2778 /* Defer clearing up the connection parameters
2779 * until closing to give a chance of keeping
2780 * them if a repairing happens.
2781 */
2782 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2783
2784 /* If disconnection is not requested, then
2785 * clear the connection variable so that the
2786 * link is not terminated.
2787 */
2788 if (!cp->disconnect)
2789 conn = NULL;
2790 }
2791
Johan Hedberge0b2b272014-02-18 17:14:31 +02002792 if (cp->addr.type == BDADDR_LE_PUBLIC)
2793 addr_type = ADDR_LE_DEV_PUBLIC;
2794 else
2795 addr_type = ADDR_LE_DEV_RANDOM;
2796
Johan Hedberga7ec7332014-02-18 17:14:35 +02002797 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2798
Johan Hedberge0b2b272014-02-18 17:14:31 +02002799 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2800 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002801
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002802 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002803 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002804 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002805 goto unlock;
2806 }
2807
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002808 /* If the connection variable is set, then termination of the
2809 * link is requested.
2810 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002811 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002812 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002813 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002814 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002815 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002816 }
2817
Johan Hedberg124f6e32012-02-09 13:50:12 +02002818 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002819 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002820 if (!cmd) {
2821 err = -ENOMEM;
2822 goto unlock;
2823 }
2824
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002825 cmd->cmd_complete = addr_cmd_complete;
2826
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002827 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002828 dc.reason = 0x13; /* Remote User Terminated Connection */
2829 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2830 if (err < 0)
2831 mgmt_pending_remove(cmd);
2832
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002833unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002834 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002835 return err;
2836}
2837
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002838static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002839 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002840{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002841 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002842 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002843 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002845 int err;
2846
2847 BT_DBG("");
2848
Johan Hedberg06a63b12013-01-20 14:27:21 +02002849 memset(&rp, 0, sizeof(rp));
2850 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2851 rp.addr.type = cp->addr.type;
2852
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002853 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002854 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2855 MGMT_STATUS_INVALID_PARAMS,
2856 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002857
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002858 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002859
2860 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002861 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2862 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002863 goto failed;
2864 }
2865
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002866 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002867 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2868 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002869 goto failed;
2870 }
2871
Andre Guedes591f47f2012-04-24 21:02:49 -03002872 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002873 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2874 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002875 else
2876 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002877
Vishal Agarwalf9607272012-06-13 05:32:43 +05302878 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002879 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2880 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002881 goto failed;
2882 }
2883
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002884 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002885 if (!cmd) {
2886 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002887 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002888 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002889
Johan Hedbergf5818c22014-12-05 13:36:02 +02002890 cmd->cmd_complete = generic_cmd_complete;
2891
Johan Hedberge3f2f922014-08-18 20:33:33 +03002892 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002893 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002894 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002895
2896failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002897 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002898 return err;
2899}
2900
Andre Guedes57c14772012-04-24 21:02:50 -03002901static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002902{
2903 switch (link_type) {
2904 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002905 switch (addr_type) {
2906 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002907 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002908
Johan Hedberg48264f02011-11-09 13:58:58 +02002909 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002910 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002911 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002912 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002913
Johan Hedberg4c659c32011-11-07 23:13:39 +02002914 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002915 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002916 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002917 }
2918}
2919
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002920static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2921 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002922{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002923 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002924 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002925 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002926 int err;
2927 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002928
2929 BT_DBG("");
2930
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002931 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002932
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002933 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002934 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002935 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002936 goto unlock;
2937 }
2938
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002939 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002940 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2941 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002942 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002943 }
2944
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002945 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002946 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002947 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002948 err = -ENOMEM;
2949 goto unlock;
2950 }
2951
Johan Hedberg2784eb42011-01-21 13:56:35 +02002952 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002953 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002954 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2955 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002956 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002957 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002958 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002959 continue;
2960 i++;
2961 }
2962
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002963 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002964
Johan Hedberg4c659c32011-11-07 23:13:39 +02002965 /* Recalculate length in case of filtered SCO connections, etc */
2966 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002967
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002968 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002969 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002970
Johan Hedberga38528f2011-01-22 06:46:43 +02002971 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002972
2973unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002974 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002975 return err;
2976}
2977
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002978static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002979 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002980{
2981 struct pending_cmd *cmd;
2982 int err;
2983
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002984 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002985 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002986 if (!cmd)
2987 return -ENOMEM;
2988
Johan Hedbergd8457692012-02-17 14:24:57 +02002989 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002990 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002991 if (err < 0)
2992 mgmt_pending_remove(cmd);
2993
2994 return err;
2995}
2996
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002997static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002998 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002999{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003000 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003001 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003002 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003003 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003004 int err;
3005
3006 BT_DBG("");
3007
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003008 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003009
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003010 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003011 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003012 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003013 goto failed;
3014 }
3015
Johan Hedbergd8457692012-02-17 14:24:57 +02003016 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003017 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003018 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003019 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003020 goto failed;
3021 }
3022
3023 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003024 struct mgmt_cp_pin_code_neg_reply ncp;
3025
3026 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003027
3028 BT_ERR("PIN code is not 16 bytes long");
3029
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003030 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003031 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003032 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003033 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003034
3035 goto failed;
3036 }
3037
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003038 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003039 if (!cmd) {
3040 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003041 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003042 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003043
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003044 cmd->cmd_complete = addr_cmd_complete;
3045
Johan Hedbergd8457692012-02-17 14:24:57 +02003046 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003047 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003048 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003049
3050 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3051 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003052 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003053
3054failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003055 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003056 return err;
3057}
3058
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003059static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3060 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003061{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003062 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003063
3064 BT_DBG("");
3065
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003066 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3067 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3068 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3069
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003070 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003071
3072 hdev->io_capability = cp->io_capability;
3073
3074 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003075 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003076
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003077 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003078
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003079 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3080 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003081}
3082
Gustavo Padovan6039aa732012-05-23 04:04:18 -03003083static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003084{
3085 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003086 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003087
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003088 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003089 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3090 continue;
3091
Johan Hedberge9a416b2011-02-19 12:05:56 -03003092 if (cmd->user_data != conn)
3093 continue;
3094
3095 return cmd;
3096 }
3097
3098 return NULL;
3099}
3100
3101static void pairing_complete(struct pending_cmd *cmd, u8 status)
3102{
3103 struct mgmt_rp_pair_device rp;
3104 struct hci_conn *conn = cmd->user_data;
3105
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003106 bacpy(&rp.addr.bdaddr, &conn->dst);
3107 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003108
Johan Hedbergaee9b2182012-02-18 15:07:59 +02003109 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003110 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003111
3112 /* So we don't get further callbacks for this connection */
3113 conn->connect_cfm_cb = NULL;
3114 conn->security_cfm_cb = NULL;
3115 conn->disconn_cfm_cb = NULL;
3116
David Herrmann76a68ba2013-04-06 20:28:37 +02003117 hci_conn_drop(conn);
Johan Hedberga664b5b2011-02-19 12:06:02 -03003118 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003119
3120 /* The device is paired so there is no need to remove
3121 * its connection parameters anymore.
3122 */
3123 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003124
3125 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003126}
3127
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003128void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3129{
3130 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3131 struct pending_cmd *cmd;
3132
3133 cmd = find_pairing(conn);
3134 if (cmd)
Johan Hedberg04ab2742014-12-05 13:36:04 +02003135 cmd->cmd_complete(cmd, status);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003136}
3137
Johan Hedberge9a416b2011-02-19 12:05:56 -03003138static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3139{
3140 struct pending_cmd *cmd;
3141
3142 BT_DBG("status %u", status);
3143
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003144 cmd = find_pairing(conn);
3145 if (!cmd)
3146 BT_DBG("Unable to find a pending command");
3147 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003148 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003149}
3150
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003151static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303152{
3153 struct pending_cmd *cmd;
3154
3155 BT_DBG("status %u", status);
3156
3157 if (!status)
3158 return;
3159
3160 cmd = find_pairing(conn);
3161 if (!cmd)
3162 BT_DBG("Unable to find a pending command");
3163 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003164 cmd->cmd_complete(cmd, mgmt_status(status));
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303165}
3166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003167static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003168 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003169{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003170 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003171 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003172 struct pending_cmd *cmd;
3173 u8 sec_level, auth_type;
3174 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003175 int err;
3176
3177 BT_DBG("");
3178
Szymon Jancf950a30e2013-01-18 12:48:07 +01003179 memset(&rp, 0, sizeof(rp));
3180 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3181 rp.addr.type = cp->addr.type;
3182
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003183 if (!bdaddr_type_is_valid(cp->addr.type))
3184 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3185 MGMT_STATUS_INVALID_PARAMS,
3186 &rp, sizeof(rp));
3187
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003188 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3189 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3190 MGMT_STATUS_INVALID_PARAMS,
3191 &rp, sizeof(rp));
3192
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003193 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003194
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003195 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003196 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3197 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003198 goto unlock;
3199 }
3200
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003201 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003202 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003203
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003204 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003205 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3206 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003207 } else {
3208 u8 addr_type;
3209
3210 /* Convert from L2CAP channel address type to HCI address type
3211 */
3212 if (cp->addr.type == BDADDR_LE_PUBLIC)
3213 addr_type = ADDR_LE_DEV_PUBLIC;
3214 else
3215 addr_type = ADDR_LE_DEV_RANDOM;
3216
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003217 /* When pairing a new device, it is expected to remember
3218 * this device for future connections. Adding the connection
3219 * parameter information ahead of time allows tracking
3220 * of the slave preferred values and will speed up any
3221 * further connection establishment.
3222 *
3223 * If connection parameters already exist, then they
3224 * will be kept and this function does nothing.
3225 */
3226 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3227
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003228 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003229 sec_level, HCI_LE_CONN_TIMEOUT,
3230 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003231 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003232
Ville Tervo30e76272011-02-22 16:10:53 -03003233 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003234 int status;
3235
3236 if (PTR_ERR(conn) == -EBUSY)
3237 status = MGMT_STATUS_BUSY;
3238 else
3239 status = MGMT_STATUS_CONNECT_FAILED;
3240
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003241 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003242 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003243 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003244 goto unlock;
3245 }
3246
3247 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003248 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003249 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003250 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003251 goto unlock;
3252 }
3253
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003254 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003255 if (!cmd) {
3256 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003257 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003258 goto unlock;
3259 }
3260
Johan Hedberg04ab2742014-12-05 13:36:04 +02003261 cmd->cmd_complete = pairing_complete;
3262
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003263 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003264 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003265 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003266 conn->security_cfm_cb = pairing_complete_cb;
3267 conn->disconn_cfm_cb = pairing_complete_cb;
3268 } else {
3269 conn->connect_cfm_cb = le_pairing_complete_cb;
3270 conn->security_cfm_cb = le_pairing_complete_cb;
3271 conn->disconn_cfm_cb = le_pairing_complete_cb;
3272 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003273
Johan Hedberge9a416b2011-02-19 12:05:56 -03003274 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003275 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003276
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003277 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003278 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279 pairing_complete(cmd, 0);
3280
3281 err = 0;
3282
3283unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003284 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285 return err;
3286}
3287
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003288static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3289 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003290{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003291 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003292 struct pending_cmd *cmd;
3293 struct hci_conn *conn;
3294 int err;
3295
3296 BT_DBG("");
3297
Johan Hedberg28424702012-02-02 04:02:29 +02003298 hci_dev_lock(hdev);
3299
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003300 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003301 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003302 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003303 goto unlock;
3304 }
3305
Johan Hedberg28424702012-02-02 04:02:29 +02003306 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3307 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003308 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003309 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003310 goto unlock;
3311 }
3312
3313 conn = cmd->user_data;
3314
3315 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003316 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003317 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003318 goto unlock;
3319 }
3320
3321 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003323 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003324 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003325unlock:
3326 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003327 return err;
3328}
3329
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003330static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003331 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003332 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003333{
Johan Hedberga5c29682011-02-19 12:05:57 -03003334 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003335 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003336 int err;
3337
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003338 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003339
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003340 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003341 err = cmd_complete(sk, hdev->id, mgmt_op,
3342 MGMT_STATUS_NOT_POWERED, addr,
3343 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003344 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003345 }
3346
Johan Hedberg1707c602013-03-15 17:07:15 -05003347 if (addr->type == BDADDR_BREDR)
3348 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003349 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003350 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003351
Johan Hedberg272d90d2012-02-09 15:26:12 +02003352 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003353 err = cmd_complete(sk, hdev->id, mgmt_op,
3354 MGMT_STATUS_NOT_CONNECTED, addr,
3355 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003356 goto done;
3357 }
3358
Johan Hedberg1707c602013-03-15 17:07:15 -05003359 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003360 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003361 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003362 err = cmd_complete(sk, hdev->id, mgmt_op,
3363 MGMT_STATUS_SUCCESS, addr,
3364 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003365 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003366 err = cmd_complete(sk, hdev->id, mgmt_op,
3367 MGMT_STATUS_FAILED, addr,
3368 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003369
Brian Gix47c15e22011-11-16 13:53:14 -08003370 goto done;
3371 }
3372
Johan Hedberg1707c602013-03-15 17:07:15 -05003373 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003374 if (!cmd) {
3375 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003376 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003377 }
3378
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003379 cmd->cmd_complete = addr_cmd_complete;
3380
Brian Gix0df4c182011-11-16 13:53:13 -08003381 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003382 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3383 struct hci_cp_user_passkey_reply cp;
3384
Johan Hedberg1707c602013-03-15 17:07:15 -05003385 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003386 cp.passkey = passkey;
3387 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3388 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003389 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3390 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003391
Johan Hedberga664b5b2011-02-19 12:06:02 -03003392 if (err < 0)
3393 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003394
Brian Gix0df4c182011-11-16 13:53:13 -08003395done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003396 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003397 return err;
3398}
3399
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303400static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3401 void *data, u16 len)
3402{
3403 struct mgmt_cp_pin_code_neg_reply *cp = data;
3404
3405 BT_DBG("");
3406
Johan Hedberg1707c602013-03-15 17:07:15 -05003407 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303408 MGMT_OP_PIN_CODE_NEG_REPLY,
3409 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3410}
3411
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003412static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3413 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003414{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003415 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003416
3417 BT_DBG("");
3418
3419 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003420 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003421 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003422
Johan Hedberg1707c602013-03-15 17:07:15 -05003423 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003424 MGMT_OP_USER_CONFIRM_REPLY,
3425 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003426}
3427
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003428static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003429 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003430{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003431 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003432
3433 BT_DBG("");
3434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003436 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3437 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003438}
3439
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003440static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3441 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003442{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003443 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003444
3445 BT_DBG("");
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448 MGMT_OP_USER_PASSKEY_REPLY,
3449 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003450}
3451
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003452static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003453 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003454{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003455 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003456
3457 BT_DBG("");
3458
Johan Hedberg1707c602013-03-15 17:07:15 -05003459 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003460 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3461 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003462}
3463
Johan Hedberg13928972013-03-15 17:07:00 -05003464static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003465{
Johan Hedberg13928972013-03-15 17:07:00 -05003466 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003467 struct hci_cp_write_local_name cp;
3468
Johan Hedberg13928972013-03-15 17:07:00 -05003469 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003470
Johan Hedberg890ea892013-03-15 17:06:52 -05003471 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003472}
3473
Johan Hedberg13928972013-03-15 17:07:00 -05003474static void set_name_complete(struct hci_dev *hdev, u8 status)
3475{
3476 struct mgmt_cp_set_local_name *cp;
3477 struct pending_cmd *cmd;
3478
3479 BT_DBG("status 0x%02x", status);
3480
3481 hci_dev_lock(hdev);
3482
3483 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3484 if (!cmd)
3485 goto unlock;
3486
3487 cp = cmd->param;
3488
3489 if (status)
3490 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3491 mgmt_status(status));
3492 else
3493 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3494 cp, sizeof(*cp));
3495
3496 mgmt_pending_remove(cmd);
3497
3498unlock:
3499 hci_dev_unlock(hdev);
3500}
3501
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003502static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003503 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003504{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003505 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003506 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003507 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003508 int err;
3509
3510 BT_DBG("");
3511
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003512 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003513
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003514 /* If the old values are the same as the new ones just return a
3515 * direct command complete event.
3516 */
3517 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3518 !memcmp(hdev->short_name, cp->short_name,
3519 sizeof(hdev->short_name))) {
3520 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3521 data, len);
3522 goto failed;
3523 }
3524
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003525 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003526
Johan Hedbergb5235a62012-02-21 14:32:24 +02003527 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003528 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003529
3530 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003531 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003532 if (err < 0)
3533 goto failed;
3534
3535 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003536 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003537
Johan Hedbergb5235a62012-02-21 14:32:24 +02003538 goto failed;
3539 }
3540
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003541 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003542 if (!cmd) {
3543 err = -ENOMEM;
3544 goto failed;
3545 }
3546
Johan Hedberg13928972013-03-15 17:07:00 -05003547 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3548
Johan Hedberg890ea892013-03-15 17:06:52 -05003549 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003550
3551 if (lmp_bredr_capable(hdev)) {
3552 update_name(&req);
3553 update_eir(&req);
3554 }
3555
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003556 /* The name is stored in the scan response data and so
3557 * no need to udpate the advertising data here.
3558 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003559 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003560 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003561
Johan Hedberg13928972013-03-15 17:07:00 -05003562 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003563 if (err < 0)
3564 mgmt_pending_remove(cmd);
3565
3566failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003567 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003568 return err;
3569}
3570
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003571static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003572 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003573{
Szymon Jancc35938b2011-03-22 13:12:21 +01003574 struct pending_cmd *cmd;
3575 int err;
3576
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003577 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003578
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003579 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003580
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003581 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003582 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003583 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003584 goto unlock;
3585 }
3586
Andre Guedes9a1a1992012-07-24 15:03:48 -03003587 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003588 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003589 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003590 goto unlock;
3591 }
3592
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003593 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003594 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003595 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003596 goto unlock;
3597 }
3598
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003599 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003600 if (!cmd) {
3601 err = -ENOMEM;
3602 goto unlock;
3603 }
3604
Johan Hedberg710f11c2014-05-26 11:21:22 +03003605 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003606 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3607 0, NULL);
3608 else
3609 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3610
Szymon Jancc35938b2011-03-22 13:12:21 +01003611 if (err < 0)
3612 mgmt_pending_remove(cmd);
3613
3614unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003615 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003616 return err;
3617}
3618
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003619static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003620 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003621{
Szymon Janc2763eda2011-03-22 13:12:22 +01003622 int err;
3623
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003624 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003625
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003626 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003627
Marcel Holtmannec109112014-01-10 02:07:30 -08003628 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3629 struct mgmt_cp_add_remote_oob_data *cp = data;
3630 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003631
Johan Hedbergc19a4952014-11-17 20:52:19 +02003632 if (cp->addr.type != BDADDR_BREDR) {
3633 err = cmd_complete(sk, hdev->id,
3634 MGMT_OP_ADD_REMOTE_OOB_DATA,
3635 MGMT_STATUS_INVALID_PARAMS,
3636 &cp->addr, sizeof(cp->addr));
3637 goto unlock;
3638 }
3639
Marcel Holtmannec109112014-01-10 02:07:30 -08003640 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003641 cp->addr.type, cp->hash,
3642 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003643 if (err < 0)
3644 status = MGMT_STATUS_FAILED;
3645 else
3646 status = MGMT_STATUS_SUCCESS;
3647
3648 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3649 status, &cp->addr, sizeof(cp->addr));
3650 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3651 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003652 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003653 u8 status;
3654
Johan Hedbergc19a4952014-11-17 20:52:19 +02003655 if (cp->addr.type != BDADDR_BREDR) {
3656 err = cmd_complete(sk, hdev->id,
3657 MGMT_OP_ADD_REMOTE_OOB_DATA,
3658 MGMT_STATUS_INVALID_PARAMS,
3659 &cp->addr, sizeof(cp->addr));
3660 goto unlock;
3661 }
3662
Johan Hedberg86df9202014-10-26 20:52:27 +01003663 if (bdaddr_type_is_le(cp->addr.type)) {
3664 rand192 = NULL;
3665 hash192 = NULL;
3666 } else {
3667 rand192 = cp->rand192;
3668 hash192 = cp->hash192;
3669 }
3670
Johan Hedberg81328d52014-10-26 20:33:47 +01003671 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003672 cp->addr.type, hash192, rand192,
3673 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003674 if (err < 0)
3675 status = MGMT_STATUS_FAILED;
3676 else
3677 status = MGMT_STATUS_SUCCESS;
3678
3679 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3680 status, &cp->addr, sizeof(cp->addr));
3681 } else {
3682 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3683 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3684 MGMT_STATUS_INVALID_PARAMS);
3685 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003686
Johan Hedbergc19a4952014-11-17 20:52:19 +02003687unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003688 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003689 return err;
3690}
3691
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003692static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003693 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003694{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003695 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003696 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003697 int err;
3698
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003699 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003700
Johan Hedbergc19a4952014-11-17 20:52:19 +02003701 if (cp->addr.type != BDADDR_BREDR)
3702 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3703 MGMT_STATUS_INVALID_PARAMS,
3704 &cp->addr, sizeof(cp->addr));
3705
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003706 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003707
Johan Hedbergeedbd582014-11-15 09:34:23 +02003708 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3709 hci_remote_oob_data_clear(hdev);
3710 status = MGMT_STATUS_SUCCESS;
3711 goto done;
3712 }
3713
Johan Hedberg6928a922014-10-26 20:46:09 +01003714 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003715 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003716 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003717 else
Szymon Janca6785be2012-12-13 15:11:21 +01003718 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003719
Johan Hedbergeedbd582014-11-15 09:34:23 +02003720done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003721 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003722 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003723
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003724 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003725 return err;
3726}
3727
Marcel Holtmann80190442014-12-04 11:36:36 +01003728static bool trigger_discovery(struct hci_request *req, u8 *status)
3729{
3730 struct hci_dev *hdev = req->hdev;
3731 struct hci_cp_le_set_scan_param param_cp;
3732 struct hci_cp_le_set_scan_enable enable_cp;
3733 struct hci_cp_inquiry inq_cp;
3734 /* General inquiry access code (GIAC) */
3735 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3736 u8 own_addr_type;
3737 int err;
3738
3739 switch (hdev->discovery.type) {
3740 case DISCOV_TYPE_BREDR:
3741 *status = mgmt_bredr_support(hdev);
3742 if (*status)
3743 return false;
3744
3745 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3746 *status = MGMT_STATUS_BUSY;
3747 return false;
3748 }
3749
3750 hci_inquiry_cache_flush(hdev);
3751
3752 memset(&inq_cp, 0, sizeof(inq_cp));
3753 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3754 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3755 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3756 break;
3757
3758 case DISCOV_TYPE_LE:
3759 case DISCOV_TYPE_INTERLEAVED:
3760 *status = mgmt_le_support(hdev);
3761 if (*status)
3762 return false;
3763
3764 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3765 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3766 *status = MGMT_STATUS_NOT_SUPPORTED;
3767 return false;
3768 }
3769
3770 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3771 /* Don't let discovery abort an outgoing
3772 * connection attempt that's using directed
3773 * advertising.
3774 */
3775 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3776 BT_CONNECT)) {
3777 *status = MGMT_STATUS_REJECTED;
3778 return false;
3779 }
3780
3781 disable_advertising(req);
3782 }
3783
3784 /* If controller is scanning, it means the background scanning
3785 * is running. Thus, we should temporarily stop it in order to
3786 * set the discovery scanning parameters.
3787 */
3788 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3789 hci_req_add_le_scan_disable(req);
3790
3791 memset(&param_cp, 0, sizeof(param_cp));
3792
3793 /* All active scans will be done with either a resolvable
3794 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003795 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003796 */
3797 err = hci_update_random_address(req, true, &own_addr_type);
3798 if (err < 0) {
3799 *status = MGMT_STATUS_FAILED;
3800 return false;
3801 }
3802
3803 param_cp.type = LE_SCAN_ACTIVE;
3804 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3805 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3806 param_cp.own_address_type = own_addr_type;
3807 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3808 &param_cp);
3809
3810 memset(&enable_cp, 0, sizeof(enable_cp));
3811 enable_cp.enable = LE_SCAN_ENABLE;
3812 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3813 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3814 &enable_cp);
3815 break;
3816
3817 default:
3818 *status = MGMT_STATUS_INVALID_PARAMS;
3819 return false;
3820 }
3821
3822 return true;
3823}
3824
Andre Guedes7c307722013-04-30 15:29:28 -03003825static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3826{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003827 struct pending_cmd *cmd;
3828 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003829
Andre Guedes7c307722013-04-30 15:29:28 -03003830 BT_DBG("status %d", status);
3831
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003832 hci_dev_lock(hdev);
3833
3834 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003835 if (!cmd)
3836 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3837
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003838 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003839 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003840 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 Hedberg2922a942014-12-05 13:36:06 +02003902 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003903 if (!cmd) {
3904 err = -ENOMEM;
3905 goto failed;
3906 }
3907
Johan Hedberg2922a942014-12-05 13:36:06 +02003908 cmd->cmd_complete = generic_cmd_complete;
3909
Marcel Holtmann22078802014-12-05 11:45:22 +01003910 /* Clear the discovery filter first to free any previously
3911 * allocated memory for the UUID list.
3912 */
3913 hci_discovery_filter_clear(hdev);
3914
Andre Guedes4aab14e2012-02-17 20:39:36 -03003915 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01003916 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03003917
Andre Guedes7c307722013-04-30 15:29:28 -03003918 hci_req_init(&req, hdev);
3919
Marcel Holtmann80190442014-12-04 11:36:36 +01003920 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003921 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003922 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003923 mgmt_pending_remove(cmd);
3924 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003925 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003926
Andre Guedes7c307722013-04-30 15:29:28 -03003927 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003928 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003929 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003930 goto failed;
3931 }
3932
3933 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003934
3935failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003936 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003937 return err;
3938}
3939
Johan Hedberg2922a942014-12-05 13:36:06 +02003940static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
3941{
3942 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
3943}
3944
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003945static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3946 void *data, u16 len)
3947{
3948 struct mgmt_cp_start_service_discovery *cp = data;
3949 struct pending_cmd *cmd;
3950 struct hci_request req;
3951 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3952 u16 uuid_count, expected_len;
3953 u8 status;
3954 int err;
3955
3956 BT_DBG("%s", hdev->name);
3957
3958 hci_dev_lock(hdev);
3959
3960 if (!hdev_is_powered(hdev)) {
3961 err = cmd_complete(sk, hdev->id,
3962 MGMT_OP_START_SERVICE_DISCOVERY,
3963 MGMT_STATUS_NOT_POWERED,
3964 &cp->type, sizeof(cp->type));
3965 goto failed;
3966 }
3967
3968 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3969 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3970 err = cmd_complete(sk, hdev->id,
3971 MGMT_OP_START_SERVICE_DISCOVERY,
3972 MGMT_STATUS_BUSY, &cp->type,
3973 sizeof(cp->type));
3974 goto failed;
3975 }
3976
3977 uuid_count = __le16_to_cpu(cp->uuid_count);
3978 if (uuid_count > max_uuid_count) {
3979 BT_ERR("service_discovery: too big uuid_count value %u",
3980 uuid_count);
3981 err = cmd_complete(sk, hdev->id,
3982 MGMT_OP_START_SERVICE_DISCOVERY,
3983 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3984 sizeof(cp->type));
3985 goto failed;
3986 }
3987
3988 expected_len = sizeof(*cp) + uuid_count * 16;
3989 if (expected_len != len) {
3990 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3991 expected_len, len);
3992 err = cmd_complete(sk, hdev->id,
3993 MGMT_OP_START_SERVICE_DISCOVERY,
3994 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3995 sizeof(cp->type));
3996 goto failed;
3997 }
3998
3999 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004000 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004001 if (!cmd) {
4002 err = -ENOMEM;
4003 goto failed;
4004 }
4005
Johan Hedberg2922a942014-12-05 13:36:06 +02004006 cmd->cmd_complete = service_discovery_cmd_complete;
4007
Marcel Holtmann22078802014-12-05 11:45:22 +01004008 /* Clear the discovery filter first to free any previously
4009 * allocated memory for the UUID list.
4010 */
4011 hci_discovery_filter_clear(hdev);
4012
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004013 hdev->discovery.type = cp->type;
4014 hdev->discovery.rssi = cp->rssi;
4015 hdev->discovery.uuid_count = uuid_count;
4016
4017 if (uuid_count > 0) {
4018 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4019 GFP_KERNEL);
4020 if (!hdev->discovery.uuids) {
4021 err = cmd_complete(sk, hdev->id,
4022 MGMT_OP_START_SERVICE_DISCOVERY,
4023 MGMT_STATUS_FAILED,
4024 &cp->type, sizeof(cp->type));
4025 mgmt_pending_remove(cmd);
4026 goto failed;
4027 }
4028 }
4029
4030 hci_req_init(&req, hdev);
4031
4032 if (!trigger_discovery(&req, &status)) {
4033 err = cmd_complete(sk, hdev->id,
4034 MGMT_OP_START_SERVICE_DISCOVERY,
4035 status, &cp->type, sizeof(cp->type));
4036 mgmt_pending_remove(cmd);
4037 goto failed;
4038 }
4039
4040 err = hci_req_run(&req, start_discovery_complete);
4041 if (err < 0) {
4042 mgmt_pending_remove(cmd);
4043 goto failed;
4044 }
4045
4046 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4047
4048failed:
4049 hci_dev_unlock(hdev);
4050 return err;
4051}
4052
Andre Guedes0e05bba2013-04-30 15:29:33 -03004053static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4054{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004055 struct pending_cmd *cmd;
4056
Andre Guedes0e05bba2013-04-30 15:29:33 -03004057 BT_DBG("status %d", status);
4058
4059 hci_dev_lock(hdev);
4060
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004061 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4062 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004063 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004064 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004065 }
4066
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004067 if (!status)
4068 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004069
Andre Guedes0e05bba2013-04-30 15:29:33 -03004070 hci_dev_unlock(hdev);
4071}
4072
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004073static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004074 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004075{
Johan Hedbergd9306502012-02-20 23:25:18 +02004076 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004077 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004078 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004079 int err;
4080
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004081 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004082
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004083 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004084
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004085 if (!hci_discovery_active(hdev)) {
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_REJECTED, &mgmt_cp->type,
4088 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004089 goto unlock;
4090 }
4091
4092 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004093 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004094 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4095 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004096 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004097 }
4098
Johan Hedberg2922a942014-12-05 13:36:06 +02004099 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004100 if (!cmd) {
4101 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004102 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004103 }
4104
Johan Hedberg2922a942014-12-05 13:36:06 +02004105 cmd->cmd_complete = generic_cmd_complete;
4106
Andre Guedes0e05bba2013-04-30 15:29:33 -03004107 hci_req_init(&req, hdev);
4108
Johan Hedberg21a60d32014-06-10 14:05:58 +03004109 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004110
Johan Hedberg21a60d32014-06-10 14:05:58 +03004111 err = hci_req_run(&req, stop_discovery_complete);
4112 if (!err) {
4113 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004114 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004115 }
4116
Johan Hedberg21a60d32014-06-10 14:05:58 +03004117 mgmt_pending_remove(cmd);
4118
4119 /* If no HCI commands were sent we're done */
4120 if (err == -ENODATA) {
4121 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4122 &mgmt_cp->type, sizeof(mgmt_cp->type));
4123 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4124 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004125
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004126unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004127 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004128 return err;
4129}
4130
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004131static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004132 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004133{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004134 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004135 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004136 int err;
4137
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004138 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004139
Johan Hedberg561aafb2012-01-04 13:31:59 +02004140 hci_dev_lock(hdev);
4141
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004142 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004143 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4144 MGMT_STATUS_FAILED, &cp->addr,
4145 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004146 goto failed;
4147 }
4148
Johan Hedberga198e7b2012-02-17 14:27:06 +02004149 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004150 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004151 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4152 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4153 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004154 goto failed;
4155 }
4156
4157 if (cp->name_known) {
4158 e->name_state = NAME_KNOWN;
4159 list_del(&e->list);
4160 } else {
4161 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004162 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004163 }
4164
Johan Hedberge3846622013-01-09 15:29:33 +02004165 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4166 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004167
4168failed:
4169 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004170 return err;
4171}
4172
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004173static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004174 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004175{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004176 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004177 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004178 int err;
4179
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004180 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004181
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004182 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004183 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4184 MGMT_STATUS_INVALID_PARAMS,
4185 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004186
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004187 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004188
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004189 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4190 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004191 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004192 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004193 goto done;
4194 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004195
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004196 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4197 sk);
4198 status = MGMT_STATUS_SUCCESS;
4199
4200done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004201 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004202 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004203
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004204 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004205
4206 return err;
4207}
4208
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004209static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004210 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004211{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004212 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004213 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004214 int err;
4215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004216 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004217
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004218 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004219 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4220 MGMT_STATUS_INVALID_PARAMS,
4221 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004222
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004223 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004224
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004225 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4226 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004227 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004228 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004229 goto done;
4230 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004231
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004232 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4233 sk);
4234 status = MGMT_STATUS_SUCCESS;
4235
4236done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004237 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004238 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004239
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004240 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004241
4242 return err;
4243}
4244
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004245static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4246 u16 len)
4247{
4248 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004249 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004250 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004251 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004252
4253 BT_DBG("%s", hdev->name);
4254
Szymon Jancc72d4b82012-03-16 16:02:57 +01004255 source = __le16_to_cpu(cp->source);
4256
4257 if (source > 0x0002)
4258 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4259 MGMT_STATUS_INVALID_PARAMS);
4260
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004261 hci_dev_lock(hdev);
4262
Szymon Jancc72d4b82012-03-16 16:02:57 +01004263 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004264 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4265 hdev->devid_product = __le16_to_cpu(cp->product);
4266 hdev->devid_version = __le16_to_cpu(cp->version);
4267
4268 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4269
Johan Hedberg890ea892013-03-15 17:06:52 -05004270 hci_req_init(&req, hdev);
4271 update_eir(&req);
4272 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004273
4274 hci_dev_unlock(hdev);
4275
4276 return err;
4277}
4278
Johan Hedberg4375f102013-09-25 13:26:10 +03004279static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4280{
4281 struct cmd_lookup match = { NULL, hdev };
4282
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304283 hci_dev_lock(hdev);
4284
Johan Hedberg4375f102013-09-25 13:26:10 +03004285 if (status) {
4286 u8 mgmt_err = mgmt_status(status);
4287
4288 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4289 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304290 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004291 }
4292
Johan Hedbergc93bd152014-07-08 15:07:48 +03004293 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4294 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4295 else
4296 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4297
Johan Hedberg4375f102013-09-25 13:26:10 +03004298 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4299 &match);
4300
4301 new_settings(hdev, match.sk);
4302
4303 if (match.sk)
4304 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304305
4306unlock:
4307 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004308}
4309
Marcel Holtmann21b51872013-10-10 09:47:53 -07004310static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4311 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004312{
4313 struct mgmt_mode *cp = data;
4314 struct pending_cmd *cmd;
4315 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004316 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004317 int err;
4318
4319 BT_DBG("request for %s", hdev->name);
4320
Johan Hedberge6fe7982013-10-02 15:45:22 +03004321 status = mgmt_le_support(hdev);
4322 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004323 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004324 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004325
4326 if (cp->val != 0x00 && cp->val != 0x01)
4327 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4328 MGMT_STATUS_INVALID_PARAMS);
4329
4330 hci_dev_lock(hdev);
4331
4332 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004333 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004334
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004335 /* The following conditions are ones which mean that we should
4336 * not do any HCI communication but directly send a mgmt
4337 * response to user space (after toggling the flag if
4338 * necessary).
4339 */
4340 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004341 hci_conn_num(hdev, LE_LINK) > 0 ||
4342 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4343 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004344 bool changed = false;
4345
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004346 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4347 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004348 changed = true;
4349 }
4350
4351 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4352 if (err < 0)
4353 goto unlock;
4354
4355 if (changed)
4356 err = new_settings(hdev, sk);
4357
4358 goto unlock;
4359 }
4360
4361 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4362 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4363 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4364 MGMT_STATUS_BUSY);
4365 goto unlock;
4366 }
4367
4368 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4369 if (!cmd) {
4370 err = -ENOMEM;
4371 goto unlock;
4372 }
4373
4374 hci_req_init(&req, hdev);
4375
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004376 if (val)
4377 enable_advertising(&req);
4378 else
4379 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004380
4381 err = hci_req_run(&req, set_advertising_complete);
4382 if (err < 0)
4383 mgmt_pending_remove(cmd);
4384
4385unlock:
4386 hci_dev_unlock(hdev);
4387 return err;
4388}
4389
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004390static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4391 void *data, u16 len)
4392{
4393 struct mgmt_cp_set_static_address *cp = data;
4394 int err;
4395
4396 BT_DBG("%s", hdev->name);
4397
Marcel Holtmann62af4442013-10-02 22:10:32 -07004398 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004399 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004400 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004401
4402 if (hdev_is_powered(hdev))
4403 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4404 MGMT_STATUS_REJECTED);
4405
4406 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4407 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4408 return cmd_status(sk, hdev->id,
4409 MGMT_OP_SET_STATIC_ADDRESS,
4410 MGMT_STATUS_INVALID_PARAMS);
4411
4412 /* Two most significant bits shall be set */
4413 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4414 return cmd_status(sk, hdev->id,
4415 MGMT_OP_SET_STATIC_ADDRESS,
4416 MGMT_STATUS_INVALID_PARAMS);
4417 }
4418
4419 hci_dev_lock(hdev);
4420
4421 bacpy(&hdev->static_addr, &cp->bdaddr);
4422
4423 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4424
4425 hci_dev_unlock(hdev);
4426
4427 return err;
4428}
4429
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004430static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4431 void *data, u16 len)
4432{
4433 struct mgmt_cp_set_scan_params *cp = data;
4434 __u16 interval, window;
4435 int err;
4436
4437 BT_DBG("%s", hdev->name);
4438
4439 if (!lmp_le_capable(hdev))
4440 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4441 MGMT_STATUS_NOT_SUPPORTED);
4442
4443 interval = __le16_to_cpu(cp->interval);
4444
4445 if (interval < 0x0004 || interval > 0x4000)
4446 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4447 MGMT_STATUS_INVALID_PARAMS);
4448
4449 window = __le16_to_cpu(cp->window);
4450
4451 if (window < 0x0004 || window > 0x4000)
4452 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4453 MGMT_STATUS_INVALID_PARAMS);
4454
Marcel Holtmann899e1072013-10-14 09:55:32 -07004455 if (window > interval)
4456 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4457 MGMT_STATUS_INVALID_PARAMS);
4458
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004459 hci_dev_lock(hdev);
4460
4461 hdev->le_scan_interval = interval;
4462 hdev->le_scan_window = window;
4463
4464 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4465
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004466 /* If background scan is running, restart it so new parameters are
4467 * loaded.
4468 */
4469 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4470 hdev->discovery.state == DISCOVERY_STOPPED) {
4471 struct hci_request req;
4472
4473 hci_req_init(&req, hdev);
4474
4475 hci_req_add_le_scan_disable(&req);
4476 hci_req_add_le_passive_scan(&req);
4477
4478 hci_req_run(&req, NULL);
4479 }
4480
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004481 hci_dev_unlock(hdev);
4482
4483 return err;
4484}
4485
Johan Hedberg33e38b32013-03-15 17:07:05 -05004486static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4487{
4488 struct pending_cmd *cmd;
4489
4490 BT_DBG("status 0x%02x", status);
4491
4492 hci_dev_lock(hdev);
4493
4494 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4495 if (!cmd)
4496 goto unlock;
4497
4498 if (status) {
4499 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4500 mgmt_status(status));
4501 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004502 struct mgmt_mode *cp = cmd->param;
4503
4504 if (cp->val)
4505 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4506 else
4507 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4508
Johan Hedberg33e38b32013-03-15 17:07:05 -05004509 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4510 new_settings(hdev, cmd->sk);
4511 }
4512
4513 mgmt_pending_remove(cmd);
4514
4515unlock:
4516 hci_dev_unlock(hdev);
4517}
4518
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004519static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004520 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004521{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004522 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004523 struct pending_cmd *cmd;
4524 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004525 int err;
4526
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004527 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004528
Johan Hedberg56f87902013-10-02 13:43:13 +03004529 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4530 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004531 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4532 MGMT_STATUS_NOT_SUPPORTED);
4533
Johan Hedberga7e80f22013-01-09 16:05:19 +02004534 if (cp->val != 0x00 && cp->val != 0x01)
4535 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4536 MGMT_STATUS_INVALID_PARAMS);
4537
Johan Hedberg5400c042012-02-21 16:40:33 +02004538 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004539 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004540 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004541
4542 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004543 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004544 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004545
4546 hci_dev_lock(hdev);
4547
Johan Hedberg05cbf292013-03-15 17:07:07 -05004548 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4549 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4550 MGMT_STATUS_BUSY);
4551 goto unlock;
4552 }
4553
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004554 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4555 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4556 hdev);
4557 goto unlock;
4558 }
4559
Johan Hedberg33e38b32013-03-15 17:07:05 -05004560 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4561 data, len);
4562 if (!cmd) {
4563 err = -ENOMEM;
4564 goto unlock;
4565 }
4566
4567 hci_req_init(&req, hdev);
4568
Johan Hedberg406d7802013-03-15 17:07:09 -05004569 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004570
4571 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004572 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004573 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004574 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004575 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004576 }
4577
Johan Hedberg33e38b32013-03-15 17:07:05 -05004578unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004579 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004580
Antti Julkuf6422ec2011-06-22 13:11:56 +03004581 return err;
4582}
4583
Johan Hedberg0663ca22013-10-02 13:43:14 +03004584static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4585{
4586 struct pending_cmd *cmd;
4587
4588 BT_DBG("status 0x%02x", status);
4589
4590 hci_dev_lock(hdev);
4591
4592 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4593 if (!cmd)
4594 goto unlock;
4595
4596 if (status) {
4597 u8 mgmt_err = mgmt_status(status);
4598
4599 /* We need to restore the flag if related HCI commands
4600 * failed.
4601 */
4602 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4603
4604 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4605 } else {
4606 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4607 new_settings(hdev, cmd->sk);
4608 }
4609
4610 mgmt_pending_remove(cmd);
4611
4612unlock:
4613 hci_dev_unlock(hdev);
4614}
4615
4616static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4617{
4618 struct mgmt_mode *cp = data;
4619 struct pending_cmd *cmd;
4620 struct hci_request req;
4621 int err;
4622
4623 BT_DBG("request for %s", hdev->name);
4624
4625 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4626 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4627 MGMT_STATUS_NOT_SUPPORTED);
4628
4629 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4630 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4631 MGMT_STATUS_REJECTED);
4632
4633 if (cp->val != 0x00 && cp->val != 0x01)
4634 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4635 MGMT_STATUS_INVALID_PARAMS);
4636
4637 hci_dev_lock(hdev);
4638
4639 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4640 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4641 goto unlock;
4642 }
4643
4644 if (!hdev_is_powered(hdev)) {
4645 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004646 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4647 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4648 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4649 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4650 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4651 }
4652
4653 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4654
4655 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4656 if (err < 0)
4657 goto unlock;
4658
4659 err = new_settings(hdev, sk);
4660 goto unlock;
4661 }
4662
4663 /* Reject disabling when powered on */
4664 if (!cp->val) {
4665 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4666 MGMT_STATUS_REJECTED);
4667 goto unlock;
4668 }
4669
4670 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4671 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4672 MGMT_STATUS_BUSY);
4673 goto unlock;
4674 }
4675
4676 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4677 if (!cmd) {
4678 err = -ENOMEM;
4679 goto unlock;
4680 }
4681
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004682 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004683 * generates the correct flags.
4684 */
4685 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4686
4687 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004688
Johan Hedberg432df052014-08-01 11:13:31 +03004689 write_fast_connectable(&req, false);
4690 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004691
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004692 /* Since only the advertising data flags will change, there
4693 * is no need to update the scan response data.
4694 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004695 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004696
Johan Hedberg0663ca22013-10-02 13:43:14 +03004697 err = hci_req_run(&req, set_bredr_complete);
4698 if (err < 0)
4699 mgmt_pending_remove(cmd);
4700
4701unlock:
4702 hci_dev_unlock(hdev);
4703 return err;
4704}
4705
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004706static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4707 void *data, u16 len)
4708{
4709 struct mgmt_mode *cp = data;
4710 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004711 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004712 int err;
4713
4714 BT_DBG("request for %s", hdev->name);
4715
Johan Hedberga3209692014-05-26 11:23:35 +03004716 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4717 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004718 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4719 MGMT_STATUS_NOT_SUPPORTED);
4720
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004721 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004722 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4723 MGMT_STATUS_INVALID_PARAMS);
4724
4725 hci_dev_lock(hdev);
4726
Johan Hedberga3209692014-05-26 11:23:35 +03004727 if (!hdev_is_powered(hdev) ||
4728 (!lmp_sc_capable(hdev) &&
4729 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4730 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004731 bool changed;
4732
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004733 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004734 changed = !test_and_set_bit(HCI_SC_ENABLED,
4735 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004736 if (cp->val == 0x02)
4737 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4738 else
4739 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4740 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004741 changed = test_and_clear_bit(HCI_SC_ENABLED,
4742 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004743 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4744 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004745
4746 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4747 if (err < 0)
4748 goto failed;
4749
4750 if (changed)
4751 err = new_settings(hdev, sk);
4752
4753 goto failed;
4754 }
4755
4756 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4757 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4758 MGMT_STATUS_BUSY);
4759 goto failed;
4760 }
4761
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004762 val = !!cp->val;
4763
4764 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4765 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004766 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4767 goto failed;
4768 }
4769
4770 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4771 if (!cmd) {
4772 err = -ENOMEM;
4773 goto failed;
4774 }
4775
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004776 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004777 if (err < 0) {
4778 mgmt_pending_remove(cmd);
4779 goto failed;
4780 }
4781
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004782 if (cp->val == 0x02)
4783 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4784 else
4785 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4786
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004787failed:
4788 hci_dev_unlock(hdev);
4789 return err;
4790}
4791
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004792static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4793 void *data, u16 len)
4794{
4795 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004796 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004797 int err;
4798
4799 BT_DBG("request for %s", hdev->name);
4800
Johan Hedbergb97109792014-06-24 14:00:28 +03004801 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004802 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4803 MGMT_STATUS_INVALID_PARAMS);
4804
4805 hci_dev_lock(hdev);
4806
4807 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004808 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4809 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004810 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004811 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4812 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004813
Johan Hedbergb97109792014-06-24 14:00:28 +03004814 if (cp->val == 0x02)
4815 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4816 &hdev->dev_flags);
4817 else
4818 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4819 &hdev->dev_flags);
4820
4821 if (hdev_is_powered(hdev) && use_changed &&
4822 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4823 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4824 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4825 sizeof(mode), &mode);
4826 }
4827
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004828 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4829 if (err < 0)
4830 goto unlock;
4831
4832 if (changed)
4833 err = new_settings(hdev, sk);
4834
4835unlock:
4836 hci_dev_unlock(hdev);
4837 return err;
4838}
4839
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004840static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4841 u16 len)
4842{
4843 struct mgmt_cp_set_privacy *cp = cp_data;
4844 bool changed;
4845 int err;
4846
4847 BT_DBG("request for %s", hdev->name);
4848
4849 if (!lmp_le_capable(hdev))
4850 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4851 MGMT_STATUS_NOT_SUPPORTED);
4852
4853 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4854 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4855 MGMT_STATUS_INVALID_PARAMS);
4856
4857 if (hdev_is_powered(hdev))
4858 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4859 MGMT_STATUS_REJECTED);
4860
4861 hci_dev_lock(hdev);
4862
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004863 /* If user space supports this command it is also expected to
4864 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4865 */
4866 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4867
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004868 if (cp->privacy) {
4869 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4870 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4871 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4872 } else {
4873 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4874 memset(hdev->irk, 0, sizeof(hdev->irk));
4875 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4876 }
4877
4878 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4879 if (err < 0)
4880 goto unlock;
4881
4882 if (changed)
4883 err = new_settings(hdev, sk);
4884
4885unlock:
4886 hci_dev_unlock(hdev);
4887 return err;
4888}
4889
Johan Hedberg41edf162014-02-18 10:19:35 +02004890static bool irk_is_valid(struct mgmt_irk_info *irk)
4891{
4892 switch (irk->addr.type) {
4893 case BDADDR_LE_PUBLIC:
4894 return true;
4895
4896 case BDADDR_LE_RANDOM:
4897 /* Two most significant bits shall be set */
4898 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4899 return false;
4900 return true;
4901 }
4902
4903 return false;
4904}
4905
4906static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4907 u16 len)
4908{
4909 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004910 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4911 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004912 u16 irk_count, expected_len;
4913 int i, err;
4914
4915 BT_DBG("request for %s", hdev->name);
4916
4917 if (!lmp_le_capable(hdev))
4918 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4919 MGMT_STATUS_NOT_SUPPORTED);
4920
4921 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004922 if (irk_count > max_irk_count) {
4923 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4924 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4925 MGMT_STATUS_INVALID_PARAMS);
4926 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004927
4928 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4929 if (expected_len != len) {
4930 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004931 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004932 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4933 MGMT_STATUS_INVALID_PARAMS);
4934 }
4935
4936 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4937
4938 for (i = 0; i < irk_count; i++) {
4939 struct mgmt_irk_info *key = &cp->irks[i];
4940
4941 if (!irk_is_valid(key))
4942 return cmd_status(sk, hdev->id,
4943 MGMT_OP_LOAD_IRKS,
4944 MGMT_STATUS_INVALID_PARAMS);
4945 }
4946
4947 hci_dev_lock(hdev);
4948
4949 hci_smp_irks_clear(hdev);
4950
4951 for (i = 0; i < irk_count; i++) {
4952 struct mgmt_irk_info *irk = &cp->irks[i];
4953 u8 addr_type;
4954
4955 if (irk->addr.type == BDADDR_LE_PUBLIC)
4956 addr_type = ADDR_LE_DEV_PUBLIC;
4957 else
4958 addr_type = ADDR_LE_DEV_RANDOM;
4959
4960 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4961 BDADDR_ANY);
4962 }
4963
4964 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4965
4966 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4967
4968 hci_dev_unlock(hdev);
4969
4970 return err;
4971}
4972
Johan Hedberg3f706b72013-01-20 14:27:16 +02004973static bool ltk_is_valid(struct mgmt_ltk_info *key)
4974{
4975 if (key->master != 0x00 && key->master != 0x01)
4976 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004977
4978 switch (key->addr.type) {
4979 case BDADDR_LE_PUBLIC:
4980 return true;
4981
4982 case BDADDR_LE_RANDOM:
4983 /* Two most significant bits shall be set */
4984 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4985 return false;
4986 return true;
4987 }
4988
4989 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004990}
4991
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004992static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004993 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004994{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004995 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004996 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4997 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004998 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004999 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005000
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005001 BT_DBG("request for %s", hdev->name);
5002
5003 if (!lmp_le_capable(hdev))
5004 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5005 MGMT_STATUS_NOT_SUPPORTED);
5006
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005007 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005008 if (key_count > max_key_count) {
5009 BT_ERR("load_ltks: too big key_count value %u", key_count);
5010 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5011 MGMT_STATUS_INVALID_PARAMS);
5012 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005013
5014 expected_len = sizeof(*cp) + key_count *
5015 sizeof(struct mgmt_ltk_info);
5016 if (expected_len != len) {
5017 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005018 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005019 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005020 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005021 }
5022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005023 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005024
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005025 for (i = 0; i < key_count; i++) {
5026 struct mgmt_ltk_info *key = &cp->keys[i];
5027
Johan Hedberg3f706b72013-01-20 14:27:16 +02005028 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005029 return cmd_status(sk, hdev->id,
5030 MGMT_OP_LOAD_LONG_TERM_KEYS,
5031 MGMT_STATUS_INVALID_PARAMS);
5032 }
5033
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005034 hci_dev_lock(hdev);
5035
5036 hci_smp_ltks_clear(hdev);
5037
5038 for (i = 0; i < key_count; i++) {
5039 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005040 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005041
5042 if (key->addr.type == BDADDR_LE_PUBLIC)
5043 addr_type = ADDR_LE_DEV_PUBLIC;
5044 else
5045 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005046
Johan Hedberg61b43352014-05-29 19:36:53 +03005047 switch (key->type) {
5048 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005049 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005050 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005051 break;
5052 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005053 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005054 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005055 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005056 case MGMT_LTK_P256_UNAUTH:
5057 authenticated = 0x00;
5058 type = SMP_LTK_P256;
5059 break;
5060 case MGMT_LTK_P256_AUTH:
5061 authenticated = 0x01;
5062 type = SMP_LTK_P256;
5063 break;
5064 case MGMT_LTK_P256_DEBUG:
5065 authenticated = 0x00;
5066 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005067 default:
5068 continue;
5069 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005070
Johan Hedberg35d70272014-02-19 14:57:47 +02005071 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005072 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005073 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005074 }
5075
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005076 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5077 NULL, 0);
5078
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005079 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005080
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005081 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005082}
5083
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005084static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005085{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005086 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005087 struct mgmt_rp_get_conn_info rp;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005088
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005089 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005090
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005091 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005092 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005093 rp.tx_power = conn->tx_power;
5094 rp.max_tx_power = conn->max_tx_power;
5095 } else {
5096 rp.rssi = HCI_RSSI_INVALID;
5097 rp.tx_power = HCI_TX_POWER_INVALID;
5098 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005099 }
5100
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005101 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5102 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005103
5104 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005105 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005106}
5107
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005108static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005109{
5110 struct hci_cp_read_rssi *cp;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005111 struct pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005112 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005113 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005114 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005115
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005116 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005117
5118 hci_dev_lock(hdev);
5119
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005120 /* Commands sent in request are either Read RSSI or Read Transmit Power
5121 * Level so we check which one was last sent to retrieve connection
5122 * handle. Both commands have handle as first parameter so it's safe to
5123 * cast data on the same command struct.
5124 *
5125 * First command sent is always Read RSSI and we fail only if it fails.
5126 * In other case we simply override error to indicate success as we
5127 * already remembered if TX power value is actually valid.
5128 */
5129 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5130 if (!cp) {
5131 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005132 status = MGMT_STATUS_SUCCESS;
5133 } else {
5134 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005135 }
5136
5137 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005138 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005139 goto unlock;
5140 }
5141
5142 handle = __le16_to_cpu(cp->handle);
5143 conn = hci_conn_hash_lookup_handle(hdev, handle);
5144 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005145 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005146 goto unlock;
5147 }
5148
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005149 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5150 if (!cmd)
5151 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005152
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005153 cmd->cmd_complete(cmd, status);
5154 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005155
5156unlock:
5157 hci_dev_unlock(hdev);
5158}
5159
5160static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5161 u16 len)
5162{
5163 struct mgmt_cp_get_conn_info *cp = data;
5164 struct mgmt_rp_get_conn_info rp;
5165 struct hci_conn *conn;
5166 unsigned long conn_info_age;
5167 int err = 0;
5168
5169 BT_DBG("%s", hdev->name);
5170
5171 memset(&rp, 0, sizeof(rp));
5172 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5173 rp.addr.type = cp->addr.type;
5174
5175 if (!bdaddr_type_is_valid(cp->addr.type))
5176 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5177 MGMT_STATUS_INVALID_PARAMS,
5178 &rp, sizeof(rp));
5179
5180 hci_dev_lock(hdev);
5181
5182 if (!hdev_is_powered(hdev)) {
5183 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5184 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5185 goto unlock;
5186 }
5187
5188 if (cp->addr.type == BDADDR_BREDR)
5189 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5190 &cp->addr.bdaddr);
5191 else
5192 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5193
5194 if (!conn || conn->state != BT_CONNECTED) {
5195 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5196 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5197 goto unlock;
5198 }
5199
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005200 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5201 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5202 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5203 goto unlock;
5204 }
5205
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005206 /* To avoid client trying to guess when to poll again for information we
5207 * calculate conn info age as random value between min/max set in hdev.
5208 */
5209 conn_info_age = hdev->conn_info_min_age +
5210 prandom_u32_max(hdev->conn_info_max_age -
5211 hdev->conn_info_min_age);
5212
5213 /* Query controller to refresh cached values if they are too old or were
5214 * never read.
5215 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005216 if (time_after(jiffies, conn->conn_info_timestamp +
5217 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005218 !conn->conn_info_timestamp) {
5219 struct hci_request req;
5220 struct hci_cp_read_tx_power req_txp_cp;
5221 struct hci_cp_read_rssi req_rssi_cp;
5222 struct pending_cmd *cmd;
5223
5224 hci_req_init(&req, hdev);
5225 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5226 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5227 &req_rssi_cp);
5228
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005229 /* For LE links TX power does not change thus we don't need to
5230 * query for it once value is known.
5231 */
5232 if (!bdaddr_type_is_le(cp->addr.type) ||
5233 conn->tx_power == HCI_TX_POWER_INVALID) {
5234 req_txp_cp.handle = cpu_to_le16(conn->handle);
5235 req_txp_cp.type = 0x00;
5236 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5237 sizeof(req_txp_cp), &req_txp_cp);
5238 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005239
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005240 /* Max TX power needs to be read only once per connection */
5241 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5242 req_txp_cp.handle = cpu_to_le16(conn->handle);
5243 req_txp_cp.type = 0x01;
5244 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5245 sizeof(req_txp_cp), &req_txp_cp);
5246 }
5247
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005248 err = hci_req_run(&req, conn_info_refresh_complete);
5249 if (err < 0)
5250 goto unlock;
5251
5252 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5253 data, len);
5254 if (!cmd) {
5255 err = -ENOMEM;
5256 goto unlock;
5257 }
5258
5259 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005260 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005261 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005262
5263 conn->conn_info_timestamp = jiffies;
5264 } else {
5265 /* Cache is valid, just reply with values cached in hci_conn */
5266 rp.rssi = conn->rssi;
5267 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005268 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005269
5270 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5271 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5272 }
5273
5274unlock:
5275 hci_dev_unlock(hdev);
5276 return err;
5277}
5278
Johan Hedberg69487372014-12-05 13:36:07 +02005279static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
5280{
5281 struct hci_conn *conn = cmd->user_data;
5282 struct mgmt_rp_get_clock_info rp;
5283 struct hci_dev *hdev;
5284
5285 memset(&rp, 0, sizeof(rp));
5286 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5287
5288 if (status)
5289 goto complete;
5290
5291 hdev = hci_dev_get(cmd->index);
5292 if (hdev) {
5293 rp.local_clock = cpu_to_le32(hdev->clock);
5294 hci_dev_put(hdev);
5295 }
5296
5297 if (conn) {
5298 rp.piconet_clock = cpu_to_le32(conn->clock);
5299 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5300 }
5301
5302complete:
5303 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
5304
5305 if (conn) {
5306 hci_conn_drop(conn);
5307 hci_conn_put(conn);
5308 }
5309}
5310
Johan Hedberg95868422014-06-28 17:54:07 +03005311static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5312{
Johan Hedberg95868422014-06-28 17:54:07 +03005313 struct hci_cp_read_clock *hci_cp;
5314 struct pending_cmd *cmd;
5315 struct hci_conn *conn;
5316
5317 BT_DBG("%s status %u", hdev->name, status);
5318
5319 hci_dev_lock(hdev);
5320
5321 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5322 if (!hci_cp)
5323 goto unlock;
5324
5325 if (hci_cp->which) {
5326 u16 handle = __le16_to_cpu(hci_cp->handle);
5327 conn = hci_conn_hash_lookup_handle(hdev, handle);
5328 } else {
5329 conn = NULL;
5330 }
5331
5332 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5333 if (!cmd)
5334 goto unlock;
5335
Johan Hedberg69487372014-12-05 13:36:07 +02005336 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005337 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005338
5339unlock:
5340 hci_dev_unlock(hdev);
5341}
5342
5343static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5344 u16 len)
5345{
5346 struct mgmt_cp_get_clock_info *cp = data;
5347 struct mgmt_rp_get_clock_info rp;
5348 struct hci_cp_read_clock hci_cp;
5349 struct pending_cmd *cmd;
5350 struct hci_request req;
5351 struct hci_conn *conn;
5352 int err;
5353
5354 BT_DBG("%s", hdev->name);
5355
5356 memset(&rp, 0, sizeof(rp));
5357 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5358 rp.addr.type = cp->addr.type;
5359
5360 if (cp->addr.type != BDADDR_BREDR)
5361 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5362 MGMT_STATUS_INVALID_PARAMS,
5363 &rp, sizeof(rp));
5364
5365 hci_dev_lock(hdev);
5366
5367 if (!hdev_is_powered(hdev)) {
5368 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5369 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5370 goto unlock;
5371 }
5372
5373 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5374 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5375 &cp->addr.bdaddr);
5376 if (!conn || conn->state != BT_CONNECTED) {
5377 err = cmd_complete(sk, hdev->id,
5378 MGMT_OP_GET_CLOCK_INFO,
5379 MGMT_STATUS_NOT_CONNECTED,
5380 &rp, sizeof(rp));
5381 goto unlock;
5382 }
5383 } else {
5384 conn = NULL;
5385 }
5386
5387 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5388 if (!cmd) {
5389 err = -ENOMEM;
5390 goto unlock;
5391 }
5392
Johan Hedberg69487372014-12-05 13:36:07 +02005393 cmd->cmd_complete = clock_info_cmd_complete;
5394
Johan Hedberg95868422014-06-28 17:54:07 +03005395 hci_req_init(&req, hdev);
5396
5397 memset(&hci_cp, 0, sizeof(hci_cp));
5398 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5399
5400 if (conn) {
5401 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005402 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005403
5404 hci_cp.handle = cpu_to_le16(conn->handle);
5405 hci_cp.which = 0x01; /* Piconet clock */
5406 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5407 }
5408
5409 err = hci_req_run(&req, get_clock_info_complete);
5410 if (err < 0)
5411 mgmt_pending_remove(cmd);
5412
5413unlock:
5414 hci_dev_unlock(hdev);
5415 return err;
5416}
5417
Marcel Holtmann8afef092014-06-29 22:28:34 +02005418static void device_added(struct sock *sk, struct hci_dev *hdev,
5419 bdaddr_t *bdaddr, u8 type, u8 action)
5420{
5421 struct mgmt_ev_device_added ev;
5422
5423 bacpy(&ev.addr.bdaddr, bdaddr);
5424 ev.addr.type = type;
5425 ev.action = action;
5426
5427 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5428}
5429
Marcel Holtmann2faade52014-06-29 19:44:03 +02005430static int add_device(struct sock *sk, struct hci_dev *hdev,
5431 void *data, u16 len)
5432{
5433 struct mgmt_cp_add_device *cp = data;
5434 u8 auto_conn, addr_type;
5435 int err;
5436
5437 BT_DBG("%s", hdev->name);
5438
Johan Hedberg66593582014-07-09 12:59:14 +03005439 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005440 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5441 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5442 MGMT_STATUS_INVALID_PARAMS,
5443 &cp->addr, sizeof(cp->addr));
5444
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005445 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005446 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5447 MGMT_STATUS_INVALID_PARAMS,
5448 &cp->addr, sizeof(cp->addr));
5449
5450 hci_dev_lock(hdev);
5451
Johan Hedberg66593582014-07-09 12:59:14 +03005452 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005453 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005454 if (cp->action != 0x01) {
5455 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5456 MGMT_STATUS_INVALID_PARAMS,
5457 &cp->addr, sizeof(cp->addr));
5458 goto unlock;
5459 }
5460
5461 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5462 cp->addr.type);
5463 if (err)
5464 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005465
Johan Hedberg432df052014-08-01 11:13:31 +03005466 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005467
Johan Hedberg66593582014-07-09 12:59:14 +03005468 goto added;
5469 }
5470
Marcel Holtmann2faade52014-06-29 19:44:03 +02005471 if (cp->addr.type == BDADDR_LE_PUBLIC)
5472 addr_type = ADDR_LE_DEV_PUBLIC;
5473 else
5474 addr_type = ADDR_LE_DEV_RANDOM;
5475
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005476 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005477 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005478 else if (cp->action == 0x01)
5479 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005480 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005481 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005482
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005483 /* If the connection parameters don't exist for this device,
5484 * they will be created and configured with defaults.
5485 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005486 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5487 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005488 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5489 MGMT_STATUS_FAILED,
5490 &cp->addr, sizeof(cp->addr));
5491 goto unlock;
5492 }
5493
Johan Hedberg66593582014-07-09 12:59:14 +03005494added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005495 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5496
Marcel Holtmann2faade52014-06-29 19:44:03 +02005497 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5498 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5499
5500unlock:
5501 hci_dev_unlock(hdev);
5502 return err;
5503}
5504
Marcel Holtmann8afef092014-06-29 22:28:34 +02005505static void device_removed(struct sock *sk, struct hci_dev *hdev,
5506 bdaddr_t *bdaddr, u8 type)
5507{
5508 struct mgmt_ev_device_removed ev;
5509
5510 bacpy(&ev.addr.bdaddr, bdaddr);
5511 ev.addr.type = type;
5512
5513 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5514}
5515
Marcel Holtmann2faade52014-06-29 19:44:03 +02005516static int remove_device(struct sock *sk, struct hci_dev *hdev,
5517 void *data, u16 len)
5518{
5519 struct mgmt_cp_remove_device *cp = data;
5520 int err;
5521
5522 BT_DBG("%s", hdev->name);
5523
5524 hci_dev_lock(hdev);
5525
5526 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005527 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005528 u8 addr_type;
5529
Johan Hedberg66593582014-07-09 12:59:14 +03005530 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005531 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5532 MGMT_STATUS_INVALID_PARAMS,
5533 &cp->addr, sizeof(cp->addr));
5534 goto unlock;
5535 }
5536
Johan Hedberg66593582014-07-09 12:59:14 +03005537 if (cp->addr.type == BDADDR_BREDR) {
5538 err = hci_bdaddr_list_del(&hdev->whitelist,
5539 &cp->addr.bdaddr,
5540 cp->addr.type);
5541 if (err) {
5542 err = cmd_complete(sk, hdev->id,
5543 MGMT_OP_REMOVE_DEVICE,
5544 MGMT_STATUS_INVALID_PARAMS,
5545 &cp->addr, sizeof(cp->addr));
5546 goto unlock;
5547 }
5548
Johan Hedberg432df052014-08-01 11:13:31 +03005549 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005550
Johan Hedberg66593582014-07-09 12:59:14 +03005551 device_removed(sk, hdev, &cp->addr.bdaddr,
5552 cp->addr.type);
5553 goto complete;
5554 }
5555
Marcel Holtmann2faade52014-06-29 19:44:03 +02005556 if (cp->addr.type == BDADDR_LE_PUBLIC)
5557 addr_type = ADDR_LE_DEV_PUBLIC;
5558 else
5559 addr_type = ADDR_LE_DEV_RANDOM;
5560
Johan Hedbergc71593d2014-07-02 17:37:28 +03005561 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5562 addr_type);
5563 if (!params) {
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
5570 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5571 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5572 MGMT_STATUS_INVALID_PARAMS,
5573 &cp->addr, sizeof(cp->addr));
5574 goto unlock;
5575 }
5576
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005577 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005578 list_del(&params->list);
5579 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005580 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005581
5582 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005583 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005584 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005585 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005586
Marcel Holtmann2faade52014-06-29 19:44:03 +02005587 if (cp->addr.type) {
5588 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5589 MGMT_STATUS_INVALID_PARAMS,
5590 &cp->addr, sizeof(cp->addr));
5591 goto unlock;
5592 }
5593
Johan Hedberg66593582014-07-09 12:59:14 +03005594 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5595 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5596 list_del(&b->list);
5597 kfree(b);
5598 }
5599
Johan Hedberg432df052014-08-01 11:13:31 +03005600 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005601
Johan Hedberg19de0822014-07-06 13:06:51 +03005602 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5603 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5604 continue;
5605 device_removed(sk, hdev, &p->addr, p->addr_type);
5606 list_del(&p->action);
5607 list_del(&p->list);
5608 kfree(p);
5609 }
5610
5611 BT_DBG("All LE connection parameters were removed");
5612
5613 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005614 }
5615
Johan Hedberg66593582014-07-09 12:59:14 +03005616complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005617 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5618 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5619
5620unlock:
5621 hci_dev_unlock(hdev);
5622 return err;
5623}
5624
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005625static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5626 u16 len)
5627{
5628 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005629 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5630 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005631 u16 param_count, expected_len;
5632 int i;
5633
5634 if (!lmp_le_capable(hdev))
5635 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5636 MGMT_STATUS_NOT_SUPPORTED);
5637
5638 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005639 if (param_count > max_param_count) {
5640 BT_ERR("load_conn_param: too big param_count value %u",
5641 param_count);
5642 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5643 MGMT_STATUS_INVALID_PARAMS);
5644 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005645
5646 expected_len = sizeof(*cp) + param_count *
5647 sizeof(struct mgmt_conn_param);
5648 if (expected_len != len) {
5649 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5650 expected_len, len);
5651 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5652 MGMT_STATUS_INVALID_PARAMS);
5653 }
5654
5655 BT_DBG("%s param_count %u", hdev->name, param_count);
5656
5657 hci_dev_lock(hdev);
5658
5659 hci_conn_params_clear_disabled(hdev);
5660
5661 for (i = 0; i < param_count; i++) {
5662 struct mgmt_conn_param *param = &cp->params[i];
5663 struct hci_conn_params *hci_param;
5664 u16 min, max, latency, timeout;
5665 u8 addr_type;
5666
5667 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5668 param->addr.type);
5669
5670 if (param->addr.type == BDADDR_LE_PUBLIC) {
5671 addr_type = ADDR_LE_DEV_PUBLIC;
5672 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5673 addr_type = ADDR_LE_DEV_RANDOM;
5674 } else {
5675 BT_ERR("Ignoring invalid connection parameters");
5676 continue;
5677 }
5678
5679 min = le16_to_cpu(param->min_interval);
5680 max = le16_to_cpu(param->max_interval);
5681 latency = le16_to_cpu(param->latency);
5682 timeout = le16_to_cpu(param->timeout);
5683
5684 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5685 min, max, latency, timeout);
5686
5687 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5688 BT_ERR("Ignoring invalid connection parameters");
5689 continue;
5690 }
5691
5692 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5693 addr_type);
5694 if (!hci_param) {
5695 BT_ERR("Failed to add connection parameters");
5696 continue;
5697 }
5698
5699 hci_param->conn_min_interval = min;
5700 hci_param->conn_max_interval = max;
5701 hci_param->conn_latency = latency;
5702 hci_param->supervision_timeout = timeout;
5703 }
5704
5705 hci_dev_unlock(hdev);
5706
5707 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5708}
5709
Marcel Holtmanndbece372014-07-04 18:11:55 +02005710static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5711 void *data, u16 len)
5712{
5713 struct mgmt_cp_set_external_config *cp = data;
5714 bool changed;
5715 int err;
5716
5717 BT_DBG("%s", hdev->name);
5718
5719 if (hdev_is_powered(hdev))
5720 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5721 MGMT_STATUS_REJECTED);
5722
5723 if (cp->config != 0x00 && cp->config != 0x01)
5724 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5725 MGMT_STATUS_INVALID_PARAMS);
5726
5727 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5728 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5729 MGMT_STATUS_NOT_SUPPORTED);
5730
5731 hci_dev_lock(hdev);
5732
5733 if (cp->config)
5734 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5735 &hdev->dev_flags);
5736 else
5737 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5738 &hdev->dev_flags);
5739
5740 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5741 if (err < 0)
5742 goto unlock;
5743
5744 if (!changed)
5745 goto unlock;
5746
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005747 err = new_options(hdev, sk);
5748
Marcel Holtmanndbece372014-07-04 18:11:55 +02005749 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5750 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005751
5752 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5753 set_bit(HCI_CONFIG, &hdev->dev_flags);
5754 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5755
5756 queue_work(hdev->req_workqueue, &hdev->power_on);
5757 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005758 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02005759 mgmt_index_added(hdev);
5760 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005761 }
5762
5763unlock:
5764 hci_dev_unlock(hdev);
5765 return err;
5766}
5767
Marcel Holtmann9713c172014-07-06 12:11:15 +02005768static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5769 void *data, u16 len)
5770{
5771 struct mgmt_cp_set_public_address *cp = data;
5772 bool changed;
5773 int err;
5774
5775 BT_DBG("%s", hdev->name);
5776
5777 if (hdev_is_powered(hdev))
5778 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5779 MGMT_STATUS_REJECTED);
5780
5781 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5782 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5783 MGMT_STATUS_INVALID_PARAMS);
5784
5785 if (!hdev->set_bdaddr)
5786 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5787 MGMT_STATUS_NOT_SUPPORTED);
5788
5789 hci_dev_lock(hdev);
5790
5791 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5792 bacpy(&hdev->public_addr, &cp->bdaddr);
5793
5794 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5795 if (err < 0)
5796 goto unlock;
5797
5798 if (!changed)
5799 goto unlock;
5800
5801 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5802 err = new_options(hdev, sk);
5803
5804 if (is_configured(hdev)) {
5805 mgmt_index_removed(hdev);
5806
5807 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5808
5809 set_bit(HCI_CONFIG, &hdev->dev_flags);
5810 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5811
5812 queue_work(hdev->req_workqueue, &hdev->power_on);
5813 }
5814
5815unlock:
5816 hci_dev_unlock(hdev);
5817 return err;
5818}
5819
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005820static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005821 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5822 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005823 bool var_len;
5824 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005825} mgmt_handlers[] = {
5826 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005827 { read_version, false, MGMT_READ_VERSION_SIZE },
5828 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5829 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5830 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5831 { set_powered, false, MGMT_SETTING_SIZE },
5832 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5833 { set_connectable, false, MGMT_SETTING_SIZE },
5834 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005835 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005836 { set_link_security, false, MGMT_SETTING_SIZE },
5837 { set_ssp, false, MGMT_SETTING_SIZE },
5838 { set_hs, false, MGMT_SETTING_SIZE },
5839 { set_le, false, MGMT_SETTING_SIZE },
5840 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5841 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5842 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5843 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5844 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5845 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5846 { disconnect, false, MGMT_DISCONNECT_SIZE },
5847 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5848 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5849 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5850 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5851 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5852 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5853 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5854 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5855 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5856 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5857 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5858 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005859 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005860 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5861 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5862 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5863 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5864 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5865 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005866 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005867 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005868 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005869 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005870 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005871 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005872 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005873 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005874 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005875 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005876 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005877 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5878 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005879 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5880 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005881 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005882 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005883 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005884 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005885};
5886
Johan Hedberg03811012010-12-08 00:21:06 +02005887int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5888{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005889 void *buf;
5890 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005891 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005892 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005893 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005894 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005895 int err;
5896
5897 BT_DBG("got %zu bytes", msglen);
5898
5899 if (msglen < sizeof(*hdr))
5900 return -EINVAL;
5901
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005902 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005903 if (!buf)
5904 return -ENOMEM;
5905
5906 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5907 err = -EFAULT;
5908 goto done;
5909 }
5910
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005911 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005912 opcode = __le16_to_cpu(hdr->opcode);
5913 index = __le16_to_cpu(hdr->index);
5914 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005915
5916 if (len != msglen - sizeof(*hdr)) {
5917 err = -EINVAL;
5918 goto done;
5919 }
5920
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005921 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005922 hdev = hci_dev_get(index);
5923 if (!hdev) {
5924 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005925 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005926 goto done;
5927 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005928
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005929 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b762014-07-06 12:11:14 +02005930 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005931 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005932 err = cmd_status(sk, index, opcode,
5933 MGMT_STATUS_INVALID_INDEX);
5934 goto done;
5935 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005936
5937 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005938 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005939 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5940 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005941 err = cmd_status(sk, index, opcode,
5942 MGMT_STATUS_INVALID_INDEX);
5943 goto done;
5944 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005945 }
5946
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005947 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005948 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005949 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005950 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005951 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005952 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005953 }
5954
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005955 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5956 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5957 err = cmd_status(sk, index, opcode,
5958 MGMT_STATUS_INVALID_INDEX);
5959 goto done;
5960 }
5961
5962 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5963 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005964 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005965 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005966 goto done;
5967 }
5968
Johan Hedbergbe22b542012-03-01 22:24:41 +02005969 handler = &mgmt_handlers[opcode];
5970
5971 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005972 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005973 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005974 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005975 goto done;
5976 }
5977
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005978 if (hdev)
5979 mgmt_init_hdev(sk, hdev);
5980
5981 cp = buf + sizeof(*hdr);
5982
Johan Hedbergbe22b542012-03-01 22:24:41 +02005983 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005984 if (err < 0)
5985 goto done;
5986
Johan Hedberg03811012010-12-08 00:21:06 +02005987 err = msglen;
5988
5989done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005990 if (hdev)
5991 hci_dev_put(hdev);
5992
Johan Hedberg03811012010-12-08 00:21:06 +02005993 kfree(buf);
5994 return err;
5995}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005996
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07005997void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02005998{
Marcel Holtmann1514b892013-10-06 08:25:01 -07005999 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006000 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006001
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006002 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6003 return;
6004
6005 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6006 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6007 else
6008 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006009}
6010
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006011void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006012{
Johan Hedberg5f159032012-03-02 03:13:19 +02006013 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006014
Marcel Holtmann1514b892013-10-06 08:25:01 -07006015 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006016 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006017
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006018 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6019 return;
6020
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006021 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006022
Marcel Holtmannedd38962014-07-02 21:30:55 +02006023 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6024 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6025 else
6026 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006027}
6028
Andre Guedes6046dc32014-02-26 20:21:51 -03006029/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006030static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006031{
6032 struct hci_conn_params *p;
6033
6034 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006035 /* Needed for AUTO_OFF case where might not "really"
6036 * have been powered off.
6037 */
6038 list_del_init(&p->action);
6039
6040 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006041 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006042 case HCI_AUTO_CONN_ALWAYS:
6043 list_add(&p->action, &hdev->pend_le_conns);
6044 break;
6045 case HCI_AUTO_CONN_REPORT:
6046 list_add(&p->action, &hdev->pend_le_reports);
6047 break;
6048 default:
6049 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006050 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006051 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006052
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006053 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006054}
6055
Johan Hedberg229ab392013-03-15 17:06:53 -05006056static void powered_complete(struct hci_dev *hdev, u8 status)
6057{
6058 struct cmd_lookup match = { NULL, hdev };
6059
6060 BT_DBG("status 0x%02x", status);
6061
6062 hci_dev_lock(hdev);
6063
Johan Hedbergd7347f32014-07-04 12:37:23 +03006064 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006065
Johan Hedberg229ab392013-03-15 17:06:53 -05006066 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6067
6068 new_settings(hdev, match.sk);
6069
6070 hci_dev_unlock(hdev);
6071
6072 if (match.sk)
6073 sock_put(match.sk);
6074}
6075
Johan Hedberg70da6242013-03-15 17:06:51 -05006076static int powered_update_hci(struct hci_dev *hdev)
6077{
Johan Hedberg890ea892013-03-15 17:06:52 -05006078 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006079 u8 link_sec;
6080
Johan Hedberg890ea892013-03-15 17:06:52 -05006081 hci_req_init(&req, hdev);
6082
Johan Hedberg70da6242013-03-15 17:06:51 -05006083 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6084 !lmp_host_ssp_capable(hdev)) {
6085 u8 ssp = 1;
6086
Johan Hedberg890ea892013-03-15 17:06:52 -05006087 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006088 }
6089
Johan Hedbergc73eee92013-04-19 18:35:21 +03006090 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6091 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006092 struct hci_cp_write_le_host_supported cp;
6093
Marcel Holtmann32226e42014-07-24 20:04:16 +02006094 cp.le = 0x01;
6095 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006096
6097 /* Check first if we already have the right
6098 * host state (host features set)
6099 */
6100 if (cp.le != lmp_host_le_capable(hdev) ||
6101 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006102 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6103 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006104 }
6105
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006106 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006107 /* Make sure the controller has a good default for
6108 * advertising data. This also applies to the case
6109 * where BR/EDR was toggled during the AUTO_OFF phase.
6110 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006111 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006112 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006113 update_scan_rsp_data(&req);
6114 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006115
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006116 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6117 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006118 }
6119
Johan Hedberg70da6242013-03-15 17:06:51 -05006120 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6121 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006122 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6123 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006124
6125 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006126 write_fast_connectable(&req, false);
6127 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006128 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006129 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006130 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006131 }
6132
Johan Hedberg229ab392013-03-15 17:06:53 -05006133 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006134}
6135
Johan Hedberg744cf192011-11-08 20:40:14 +02006136int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006137{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006138 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006139 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6140 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006141 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006142
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006143 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6144 return 0;
6145
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006146 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006147 if (powered_update_hci(hdev) == 0)
6148 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006149
Johan Hedberg229ab392013-03-15 17:06:53 -05006150 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6151 &match);
6152 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006153 }
6154
Johan Hedberg229ab392013-03-15 17:06:53 -05006155 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006156 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006157
6158 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6159 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6160 zero_cod, sizeof(zero_cod), NULL);
6161
6162new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006163 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006164
6165 if (match.sk)
6166 sock_put(match.sk);
6167
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006168 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006169}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006170
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006171void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006172{
6173 struct pending_cmd *cmd;
6174 u8 status;
6175
6176 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6177 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006178 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006179
6180 if (err == -ERFKILL)
6181 status = MGMT_STATUS_RFKILLED;
6182 else
6183 status = MGMT_STATUS_FAILED;
6184
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006185 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006186
6187 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006188}
6189
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006190void mgmt_discoverable_timeout(struct hci_dev *hdev)
6191{
6192 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006193
6194 hci_dev_lock(hdev);
6195
6196 /* When discoverable timeout triggers, then just make sure
6197 * the limited discoverable flag is cleared. Even in the case
6198 * of a timeout triggered from general discoverable, it is
6199 * safe to unconditionally clear the flag.
6200 */
6201 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006202 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006203
6204 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006205 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6206 u8 scan = SCAN_PAGE;
6207 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6208 sizeof(scan), &scan);
6209 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006210 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006211 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006212 hci_req_run(&req, NULL);
6213
6214 hdev->discov_timeout = 0;
6215
Johan Hedberg9a43e252013-10-20 19:00:07 +03006216 new_settings(hdev, NULL);
6217
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006218 hci_dev_unlock(hdev);
6219}
6220
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006221void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6222 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006223{
Johan Hedberg86742e12011-11-07 23:13:38 +02006224 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006225
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006226 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006227
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006228 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006229 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006230 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006231 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006232 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006233 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006234
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006235 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006236}
Johan Hedbergf7520542011-01-20 12:34:39 +02006237
Johan Hedbergd7b25452014-05-23 13:19:53 +03006238static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6239{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006240 switch (ltk->type) {
6241 case SMP_LTK:
6242 case SMP_LTK_SLAVE:
6243 if (ltk->authenticated)
6244 return MGMT_LTK_AUTHENTICATED;
6245 return MGMT_LTK_UNAUTHENTICATED;
6246 case SMP_LTK_P256:
6247 if (ltk->authenticated)
6248 return MGMT_LTK_P256_AUTH;
6249 return MGMT_LTK_P256_UNAUTH;
6250 case SMP_LTK_P256_DEBUG:
6251 return MGMT_LTK_P256_DEBUG;
6252 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006253
6254 return MGMT_LTK_UNAUTHENTICATED;
6255}
6256
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006257void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006258{
6259 struct mgmt_ev_new_long_term_key ev;
6260
6261 memset(&ev, 0, sizeof(ev));
6262
Marcel Holtmann5192d302014-02-19 17:11:58 -08006263 /* Devices using resolvable or non-resolvable random addresses
6264 * without providing an indentity resolving key don't require
6265 * to store long term keys. Their addresses will change the
6266 * next time around.
6267 *
6268 * Only when a remote device provides an identity address
6269 * make sure the long term key is stored. If the remote
6270 * identity is known, the long term keys are internally
6271 * mapped to the identity address. So allow static random
6272 * and public addresses here.
6273 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006274 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6275 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6276 ev.store_hint = 0x00;
6277 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006278 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006279
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006280 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006281 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006282 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006283 ev.key.enc_size = key->enc_size;
6284 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006285 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006286
Johan Hedberg2ceba532014-06-16 19:25:16 +03006287 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006288 ev.key.master = 1;
6289
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006290 memcpy(ev.key.val, key->val, sizeof(key->val));
6291
Marcel Holtmann083368f2013-10-15 14:26:29 -07006292 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006293}
6294
Johan Hedberg95fbac82014-02-19 15:18:31 +02006295void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6296{
6297 struct mgmt_ev_new_irk ev;
6298
6299 memset(&ev, 0, sizeof(ev));
6300
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006301 /* For identity resolving keys from devices that are already
6302 * using a public address or static random address, do not
6303 * ask for storing this key. The identity resolving key really
6304 * is only mandatory for devices using resovlable random
6305 * addresses.
6306 *
6307 * Storing all identity resolving keys has the downside that
6308 * they will be also loaded on next boot of they system. More
6309 * identity resolving keys, means more time during scanning is
6310 * needed to actually resolve these addresses.
6311 */
6312 if (bacmp(&irk->rpa, BDADDR_ANY))
6313 ev.store_hint = 0x01;
6314 else
6315 ev.store_hint = 0x00;
6316
Johan Hedberg95fbac82014-02-19 15:18:31 +02006317 bacpy(&ev.rpa, &irk->rpa);
6318 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6319 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6320 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6321
6322 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6323}
6324
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006325void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6326 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006327{
6328 struct mgmt_ev_new_csrk ev;
6329
6330 memset(&ev, 0, sizeof(ev));
6331
6332 /* Devices using resolvable or non-resolvable random addresses
6333 * without providing an indentity resolving key don't require
6334 * to store signature resolving keys. Their addresses will change
6335 * the next time around.
6336 *
6337 * Only when a remote device provides an identity address
6338 * make sure the signature resolving key is stored. So allow
6339 * static random and public addresses here.
6340 */
6341 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6342 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6343 ev.store_hint = 0x00;
6344 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006345 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006346
6347 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6348 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6349 ev.key.master = csrk->master;
6350 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6351
6352 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6353}
6354
Andre Guedesffb5a8272014-07-01 18:10:11 -03006355void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006356 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6357 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006358{
6359 struct mgmt_ev_new_conn_param ev;
6360
Johan Hedbergc103aea2014-07-02 17:37:34 +03006361 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6362 return;
6363
Andre Guedesffb5a8272014-07-01 18:10:11 -03006364 memset(&ev, 0, sizeof(ev));
6365 bacpy(&ev.addr.bdaddr, bdaddr);
6366 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006367 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006368 ev.min_interval = cpu_to_le16(min_interval);
6369 ev.max_interval = cpu_to_le16(max_interval);
6370 ev.latency = cpu_to_le16(latency);
6371 ev.timeout = cpu_to_le16(timeout);
6372
6373 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6374}
6375
Marcel Holtmann94933992013-10-15 10:26:39 -07006376static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6377 u8 data_len)
6378{
6379 eir[eir_len++] = sizeof(type) + data_len;
6380 eir[eir_len++] = type;
6381 memcpy(&eir[eir_len], data, data_len);
6382 eir_len += data_len;
6383
6384 return eir_len;
6385}
6386
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006387void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6388 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006389{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006390 char buf[512];
6391 struct mgmt_ev_device_connected *ev = (void *) buf;
6392 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006393
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006394 bacpy(&ev->addr.bdaddr, &conn->dst);
6395 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006396
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006397 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006398
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006399 /* We must ensure that the EIR Data fields are ordered and
6400 * unique. Keep it simple for now and avoid the problem by not
6401 * adding any BR/EDR data to the LE adv.
6402 */
6403 if (conn->le_adv_data_len > 0) {
6404 memcpy(&ev->eir[eir_len],
6405 conn->le_adv_data, conn->le_adv_data_len);
6406 eir_len = conn->le_adv_data_len;
6407 } else {
6408 if (name_len > 0)
6409 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6410 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006411
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006412 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006413 eir_len = eir_append_data(ev->eir, eir_len,
6414 EIR_CLASS_OF_DEV,
6415 conn->dev_class, 3);
6416 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006417
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006418 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006419
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006420 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6421 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006422}
6423
Johan Hedberg8962ee72011-01-20 12:40:27 +02006424static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6425{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006426 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006427
Johan Hedbergf5818c22014-12-05 13:36:02 +02006428 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006429
6430 *sk = cmd->sk;
6431 sock_hold(*sk);
6432
Johan Hedberga664b5b2011-02-19 12:06:02 -03006433 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006434}
6435
Johan Hedberg124f6e32012-02-09 13:50:12 +02006436static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006437{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006438 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006439 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006440
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006441 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6442
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006443 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006444 mgmt_pending_remove(cmd);
6445}
6446
Johan Hedberg84c61d92014-08-01 11:13:30 +03006447bool mgmt_powering_down(struct hci_dev *hdev)
6448{
6449 struct pending_cmd *cmd;
6450 struct mgmt_mode *cp;
6451
6452 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6453 if (!cmd)
6454 return false;
6455
6456 cp = cmd->param;
6457 if (!cp->val)
6458 return true;
6459
6460 return false;
6461}
6462
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006463void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006464 u8 link_type, u8 addr_type, u8 reason,
6465 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006466{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006467 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006468 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006469
Johan Hedberg84c61d92014-08-01 11:13:30 +03006470 /* The connection is still in hci_conn_hash so test for 1
6471 * instead of 0 to know if this is the last one.
6472 */
6473 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6474 cancel_delayed_work(&hdev->power_off);
6475 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006476 }
6477
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006478 if (!mgmt_connected)
6479 return;
6480
Andre Guedes57eb7762013-10-30 19:01:41 -03006481 if (link_type != ACL_LINK && link_type != LE_LINK)
6482 return;
6483
Johan Hedberg744cf192011-11-08 20:40:14 +02006484 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006485
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006486 bacpy(&ev.addr.bdaddr, bdaddr);
6487 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6488 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006489
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006490 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006491
6492 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006493 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006494
Johan Hedberg124f6e32012-02-09 13:50:12 +02006495 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006496 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006497}
6498
Marcel Holtmann78929242013-10-06 23:55:47 -07006499void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6500 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006501{
Andre Guedes3655bba2013-10-30 19:01:40 -03006502 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6503 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006504 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006505
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006506 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6507 hdev);
6508
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006509 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006510 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006511 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006512
Andre Guedes3655bba2013-10-30 19:01:40 -03006513 cp = cmd->param;
6514
6515 if (bacmp(bdaddr, &cp->addr.bdaddr))
6516 return;
6517
6518 if (cp->addr.type != bdaddr_type)
6519 return;
6520
Johan Hedbergf5818c22014-12-05 13:36:02 +02006521 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006522 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006523}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006524
Marcel Holtmann445608d2013-10-06 23:55:48 -07006525void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6526 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006527{
6528 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006529
Johan Hedberg84c61d92014-08-01 11:13:30 +03006530 /* The connection is still in hci_conn_hash so test for 1
6531 * instead of 0 to know if this is the last one.
6532 */
6533 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6534 cancel_delayed_work(&hdev->power_off);
6535 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006536 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006537
Johan Hedberg4c659c32011-11-07 23:13:39 +02006538 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006539 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006540 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006541
Marcel Holtmann445608d2013-10-06 23:55:48 -07006542 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006543}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006544
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006545void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006546{
6547 struct mgmt_ev_pin_code_request ev;
6548
Johan Hedbergd8457692012-02-17 14:24:57 +02006549 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006550 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006551 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006552
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006553 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006554}
6555
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006556void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6557 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006558{
6559 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006560
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006561 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006562 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006563 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006564
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006565 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006566 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006567}
6568
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006569void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6570 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006571{
6572 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006573
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006574 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006575 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006576 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006577
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006578 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006579 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006580}
Johan Hedberga5c29682011-02-19 12:05:57 -03006581
Johan Hedberg744cf192011-11-08 20:40:14 +02006582int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006583 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006584 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006585{
6586 struct mgmt_ev_user_confirm_request ev;
6587
Johan Hedberg744cf192011-11-08 20:40:14 +02006588 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006589
Johan Hedberg272d90d2012-02-09 15:26:12 +02006590 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006591 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006592 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006593 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006594
Johan Hedberg744cf192011-11-08 20:40:14 +02006595 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006596 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006597}
6598
Johan Hedberg272d90d2012-02-09 15:26:12 +02006599int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006600 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006601{
6602 struct mgmt_ev_user_passkey_request ev;
6603
6604 BT_DBG("%s", hdev->name);
6605
Johan Hedberg272d90d2012-02-09 15:26:12 +02006606 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006607 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006608
6609 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006610 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006611}
6612
Brian Gix0df4c182011-11-16 13:53:13 -08006613static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006614 u8 link_type, u8 addr_type, u8 status,
6615 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006616{
6617 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006618
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006619 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006620 if (!cmd)
6621 return -ENOENT;
6622
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006623 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006624 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006625
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006626 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006627}
6628
Johan Hedberg744cf192011-11-08 20:40:14 +02006629int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006630 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006631{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006632 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006633 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006634}
6635
Johan Hedberg272d90d2012-02-09 15:26:12 +02006636int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006637 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006638{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006639 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006640 status,
6641 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006642}
Johan Hedberg2a611692011-02-19 12:06:00 -03006643
Brian Gix604086b2011-11-23 08:28:33 -08006644int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006645 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006646{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006647 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006648 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006649}
6650
Johan Hedberg272d90d2012-02-09 15:26:12 +02006651int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006652 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006653{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006654 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006655 status,
6656 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006657}
6658
Johan Hedberg92a25252012-09-06 18:39:26 +03006659int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6660 u8 link_type, u8 addr_type, u32 passkey,
6661 u8 entered)
6662{
6663 struct mgmt_ev_passkey_notify ev;
6664
6665 BT_DBG("%s", hdev->name);
6666
6667 bacpy(&ev.addr.bdaddr, bdaddr);
6668 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6669 ev.passkey = __cpu_to_le32(passkey);
6670 ev.entered = entered;
6671
6672 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6673}
6674
Johan Hedberge1e930f2014-09-08 17:09:49 -07006675void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006676{
6677 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006678 struct pending_cmd *cmd;
6679 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006680
Johan Hedberge1e930f2014-09-08 17:09:49 -07006681 bacpy(&ev.addr.bdaddr, &conn->dst);
6682 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6683 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006684
Johan Hedberge1e930f2014-09-08 17:09:49 -07006685 cmd = find_pairing(conn);
6686
6687 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6688 cmd ? cmd->sk : NULL);
6689
6690 if (cmd)
6691 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006692}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006693
Marcel Holtmann464996a2013-10-15 14:26:24 -07006694void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006695{
6696 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006697 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006698
6699 if (status) {
6700 u8 mgmt_err = mgmt_status(status);
6701 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006702 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006703 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006704 }
6705
Marcel Holtmann464996a2013-10-15 14:26:24 -07006706 if (test_bit(HCI_AUTH, &hdev->flags))
6707 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6708 &hdev->dev_flags);
6709 else
6710 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6711 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006712
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006713 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006714 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006715
Johan Hedberg47990ea2012-02-22 11:58:37 +02006716 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006717 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006718
6719 if (match.sk)
6720 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006721}
6722
Johan Hedberg890ea892013-03-15 17:06:52 -05006723static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006724{
Johan Hedberg890ea892013-03-15 17:06:52 -05006725 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006726 struct hci_cp_write_eir cp;
6727
Johan Hedberg976eb202012-10-24 21:12:01 +03006728 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006729 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006730
Johan Hedbergc80da272012-02-22 15:38:48 +02006731 memset(hdev->eir, 0, sizeof(hdev->eir));
6732
Johan Hedbergcacaf522012-02-21 00:52:42 +02006733 memset(&cp, 0, sizeof(cp));
6734
Johan Hedberg890ea892013-03-15 17:06:52 -05006735 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006736}
6737
Marcel Holtmann3e248562013-10-15 14:26:25 -07006738void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006739{
6740 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006741 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006742 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006743
6744 if (status) {
6745 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006746
6747 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006748 &hdev->dev_flags)) {
6749 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006750 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006751 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006752
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006753 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6754 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006755 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006756 }
6757
6758 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006759 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006760 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006761 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6762 if (!changed)
6763 changed = test_and_clear_bit(HCI_HS_ENABLED,
6764 &hdev->dev_flags);
6765 else
6766 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006767 }
6768
6769 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6770
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006771 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006772 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006773
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006774 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006775 sock_put(match.sk);
6776
Johan Hedberg890ea892013-03-15 17:06:52 -05006777 hci_req_init(&req, hdev);
6778
Johan Hedberg37699722014-06-24 14:00:27 +03006779 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6780 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6781 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6782 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006783 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006784 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006785 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006786 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006787
6788 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006789}
6790
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006791void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6792{
6793 struct cmd_lookup match = { NULL, hdev };
6794 bool changed = false;
6795
6796 if (status) {
6797 u8 mgmt_err = mgmt_status(status);
6798
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006799 if (enable) {
6800 if (test_and_clear_bit(HCI_SC_ENABLED,
6801 &hdev->dev_flags))
6802 new_settings(hdev, NULL);
6803 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6804 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006805
6806 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6807 cmd_status_rsp, &mgmt_err);
6808 return;
6809 }
6810
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006811 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006812 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006813 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006814 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006815 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6816 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006817
6818 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6819 settings_rsp, &match);
6820
6821 if (changed)
6822 new_settings(hdev, match.sk);
6823
6824 if (match.sk)
6825 sock_put(match.sk);
6826}
6827
Johan Hedberg92da6092013-03-15 17:06:55 -05006828static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006829{
6830 struct cmd_lookup *match = data;
6831
Johan Hedberg90e70452012-02-23 23:09:40 +02006832 if (match->sk == NULL) {
6833 match->sk = cmd->sk;
6834 sock_hold(match->sk);
6835 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006836}
6837
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006838void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6839 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006840{
Johan Hedberg90e70452012-02-23 23:09:40 +02006841 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006842
Johan Hedberg92da6092013-03-15 17:06:55 -05006843 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6844 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6845 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006846
6847 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006848 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6849 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006850
6851 if (match.sk)
6852 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006853}
6854
Marcel Holtmann7667da32013-10-15 14:26:27 -07006855void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006856{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006857 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006858 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006859
Johan Hedberg13928972013-03-15 17:07:00 -05006860 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006861 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006862
6863 memset(&ev, 0, sizeof(ev));
6864 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006865 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006866
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006867 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006868 if (!cmd) {
6869 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006870
Johan Hedberg13928972013-03-15 17:07:00 -05006871 /* If this is a HCI command related to powering on the
6872 * HCI dev don't send any mgmt signals.
6873 */
6874 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006875 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006876 }
6877
Marcel Holtmann7667da32013-10-15 14:26:27 -07006878 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6879 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006880}
Szymon Jancc35938b2011-03-22 13:12:21 +01006881
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006882void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006883 u8 *rand192, u8 *hash256, u8 *rand256,
6884 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006885{
6886 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006887
Johan Hedberg744cf192011-11-08 20:40:14 +02006888 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006889
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006890 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006891 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006892 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006893
6894 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006895 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6896 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006897 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006898 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006899 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006900
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006901 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006902 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006903
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006904 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006905 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006906
6907 cmd_complete(cmd->sk, hdev->id,
6908 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6909 &rp, sizeof(rp));
6910 } else {
6911 struct mgmt_rp_read_local_oob_data rp;
6912
6913 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006914 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006915
6916 cmd_complete(cmd->sk, hdev->id,
6917 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6918 &rp, sizeof(rp));
6919 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006920 }
6921
6922 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006923}
Johan Hedberge17acd42011-03-30 23:57:16 +03006924
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006925static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6926{
6927 int i;
6928
6929 for (i = 0; i < uuid_count; i++) {
6930 if (!memcmp(uuid, uuids[i], 16))
6931 return true;
6932 }
6933
6934 return false;
6935}
6936
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006937static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6938{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006939 u16 parsed = 0;
6940
6941 while (parsed < eir_len) {
6942 u8 field_len = eir[0];
6943 u8 uuid[16];
6944 int i;
6945
6946 if (field_len == 0)
6947 break;
6948
6949 if (eir_len - parsed < field_len + 1)
6950 break;
6951
6952 switch (eir[1]) {
6953 case EIR_UUID16_ALL:
6954 case EIR_UUID16_SOME:
6955 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02006956 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006957 uuid[13] = eir[i + 3];
6958 uuid[12] = eir[i + 2];
6959 if (has_uuid(uuid, uuid_count, uuids))
6960 return true;
6961 }
6962 break;
6963 case EIR_UUID32_ALL:
6964 case EIR_UUID32_SOME:
6965 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02006966 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006967 uuid[15] = eir[i + 5];
6968 uuid[14] = eir[i + 4];
6969 uuid[13] = eir[i + 3];
6970 uuid[12] = eir[i + 2];
6971 if (has_uuid(uuid, uuid_count, uuids))
6972 return true;
6973 }
6974 break;
6975 case EIR_UUID128_ALL:
6976 case EIR_UUID128_SOME:
6977 for (i = 0; i + 17 <= field_len; i += 16) {
6978 memcpy(uuid, eir + i + 2, 16);
6979 if (has_uuid(uuid, uuid_count, uuids))
6980 return true;
6981 }
6982 break;
6983 }
6984
6985 parsed += field_len + 1;
6986 eir += field_len + 1;
6987 }
6988
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006989 return false;
6990}
6991
Marcel Holtmann901801b2013-10-06 23:55:51 -07006992void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02006993 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
6994 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03006995{
Johan Hedberge319d2e2012-01-15 19:51:59 +02006996 char buf[512];
6997 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02006998 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006999 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007000
Johan Hedberg75ce2082014-07-02 22:42:01 +03007001 /* Don't send events for a non-kernel initiated discovery. With
7002 * LE one exception is if we have pend_le_reports > 0 in which
7003 * case we're doing passive scanning and want these events.
7004 */
7005 if (!hci_discovery_active(hdev)) {
7006 if (link_type == ACL_LINK)
7007 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007008 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007009 return;
7010 }
Andre Guedes12602d02013-04-30 15:29:40 -03007011
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007012 /* When using service discovery with a RSSI threshold, then check
7013 * if such a RSSI threshold is specified. If a RSSI threshold has
7014 * been specified, then all results with a RSSI smaller than the
7015 * RSSI threshold will be dropped.
Marcel Holtmannefb25132014-12-05 13:03:34 +01007016 *
7017 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7018 * the results are also dropped.
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007019 */
7020 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
Marcel Holtmannefb25132014-12-05 13:03:34 +01007021 (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007022 return;
7023
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007024 /* Make sure that the buffer is big enough. The 5 extra bytes
7025 * are for the potential CoD field.
7026 */
7027 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007028 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007029
Johan Hedberg1dc06092012-01-15 21:01:23 +02007030 memset(buf, 0, sizeof(buf));
7031
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007032 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7033 * RSSI value was reported as 0 when not available. This behavior
7034 * is kept when using device discovery. This is required for full
7035 * backwards compatibility with the API.
7036 *
7037 * However when using service discovery, the value 127 will be
7038 * returned when the RSSI is not available.
7039 */
7040 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007041 rssi = 0;
7042
Johan Hedberg841c5642014-07-07 12:45:54 +03007043 bacpy(&ev->addr.bdaddr, bdaddr);
7044 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007045 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007046 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007047
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007048 if (eir_len > 0) {
7049 /* When using service discovery and a list of UUID is
7050 * provided, results with no matching UUID should be
7051 * dropped. In case there is a match the result is
7052 * kept and checking possible scan response data
7053 * will be skipped.
7054 */
7055 if (hdev->discovery.uuid_count > 0) {
7056 match = eir_has_uuids(eir, eir_len,
7057 hdev->discovery.uuid_count,
7058 hdev->discovery.uuids);
7059 if (!match)
7060 return;
7061 }
7062
7063 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007064 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007065 } else {
7066 /* When using service discovery and a list of UUID is
7067 * provided, results with empty EIR or advertising data
7068 * should be dropped since they do not match any UUID.
7069 */
7070 if (hdev->discovery.uuid_count > 0)
7071 return;
7072 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007073
Johan Hedberg1dc06092012-01-15 21:01:23 +02007074 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7075 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007076 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007077
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007078 if (scan_rsp_len > 0) {
7079 /* When using service discovery and a list of UUID is
7080 * provided, results with no matching UUID should be
7081 * dropped if there is no previous match from the
7082 * advertising data.
7083 */
7084 if (hdev->discovery.uuid_count > 0) {
7085 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7086 hdev->discovery.uuid_count,
7087 hdev->discovery.uuids))
7088 return;
7089 }
7090
7091 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007092 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007093 } else {
7094 /* When using service discovery and a list of UUID is
7095 * provided, results with empty scan response and no
7096 * previous matched advertising data should be dropped.
7097 */
7098 if (hdev->discovery.uuid_count > 0 && !match)
7099 return;
7100 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007101
7102 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7103 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007104
Marcel Holtmann901801b2013-10-06 23:55:51 -07007105 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007106}
Johan Hedberga88a9652011-03-30 13:18:12 +03007107
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007108void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7109 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007110{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007111 struct mgmt_ev_device_found *ev;
7112 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7113 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007114
Johan Hedbergb644ba32012-01-17 21:48:47 +02007115 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007116
Johan Hedbergb644ba32012-01-17 21:48:47 +02007117 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007118
Johan Hedbergb644ba32012-01-17 21:48:47 +02007119 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007120 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007121 ev->rssi = rssi;
7122
7123 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007124 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007125
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007126 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007127
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007128 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007129}
Johan Hedberg314b2382011-04-27 10:29:57 -04007130
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007131void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007132{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007133 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007134
Andre Guedes343fb142011-11-22 17:14:19 -03007135 BT_DBG("%s discovering %u", hdev->name, discovering);
7136
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007137 memset(&ev, 0, sizeof(ev));
7138 ev.type = hdev->discovery.type;
7139 ev.discovering = discovering;
7140
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007141 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007142}
Antti Julku5e762442011-08-25 16:48:02 +03007143
Marcel Holtmann5976e602013-10-06 04:08:14 -07007144static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7145{
7146 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007147}
7148
7149void mgmt_reenable_advertising(struct hci_dev *hdev)
7150{
7151 struct hci_request req;
7152
Marcel Holtmann5976e602013-10-06 04:08:14 -07007153 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7154 return;
7155
7156 hci_req_init(&req, hdev);
7157 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007158 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007159}