blob: 8467d3552aa9f5d233c708ceb3d550ec5c7a832b [file] [log] [blame]
Johan Hedberg03811012010-12-08 00:21:06 +02001/*
2 BlueZ - Bluetooth protocol stack for Linux
Johan Hedbergea585ab2012-02-17 14:50:39 +02003
Johan Hedberg03811012010-12-08 00:21:06 +02004 Copyright (C) 2010 Nokia Corporation
Johan Hedbergea585ab2012-02-17 14:50:39 +02005 Copyright (C) 2011-2012 Intel Corporation
Johan Hedberg03811012010-12-08 00:21:06 +02006
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
15 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
20 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
22 SOFTWARE IS DISCLAIMED.
23*/
24
25/* Bluetooth HCI Management interface */
26
Paul Gortmaker3a9a2312011-05-27 09:12:25 -040027#include <linux/module.h>
Johan Hedberg03811012010-12-08 00:21:06 +020028#include <asm/unaligned.h>
29
30#include <net/bluetooth/bluetooth.h>
31#include <net/bluetooth/hci_core.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030032#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020033#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070034
35#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020036
Johan Hedberg2da9c552012-02-17 14:39:28 +020037#define MGMT_VERSION 1
Marcel Holtmann854bda12014-12-03 19:52:43 +010038#define MGMT_REVISION 8
Johan Hedberg02d98122010-12-13 21:07:04 +020039
Johan Hedberge70bb2e2012-02-13 16:59:33 +020040static const u16 mgmt_commands[] = {
41 MGMT_OP_READ_INDEX_LIST,
42 MGMT_OP_READ_INFO,
43 MGMT_OP_SET_POWERED,
44 MGMT_OP_SET_DISCOVERABLE,
45 MGMT_OP_SET_CONNECTABLE,
46 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030047 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020048 MGMT_OP_SET_LINK_SECURITY,
49 MGMT_OP_SET_SSP,
50 MGMT_OP_SET_HS,
51 MGMT_OP_SET_LE,
52 MGMT_OP_SET_DEV_CLASS,
53 MGMT_OP_SET_LOCAL_NAME,
54 MGMT_OP_ADD_UUID,
55 MGMT_OP_REMOVE_UUID,
56 MGMT_OP_LOAD_LINK_KEYS,
57 MGMT_OP_LOAD_LONG_TERM_KEYS,
58 MGMT_OP_DISCONNECT,
59 MGMT_OP_GET_CONNECTIONS,
60 MGMT_OP_PIN_CODE_REPLY,
61 MGMT_OP_PIN_CODE_NEG_REPLY,
62 MGMT_OP_SET_IO_CAPABILITY,
63 MGMT_OP_PAIR_DEVICE,
64 MGMT_OP_CANCEL_PAIR_DEVICE,
65 MGMT_OP_UNPAIR_DEVICE,
66 MGMT_OP_USER_CONFIRM_REPLY,
67 MGMT_OP_USER_CONFIRM_NEG_REPLY,
68 MGMT_OP_USER_PASSKEY_REPLY,
69 MGMT_OP_USER_PASSKEY_NEG_REPLY,
70 MGMT_OP_READ_LOCAL_OOB_DATA,
71 MGMT_OP_ADD_REMOTE_OOB_DATA,
72 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
73 MGMT_OP_START_DISCOVERY,
74 MGMT_OP_STOP_DISCOVERY,
75 MGMT_OP_CONFIRM_NAME,
76 MGMT_OP_BLOCK_DEVICE,
77 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070078 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030079 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030080 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070081 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070082 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080083 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080084 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020085 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020086 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020087 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030088 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020089 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030091 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020092 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020093 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020094 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020095 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010096 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020097};
98
99static const u16 mgmt_events[] = {
100 MGMT_EV_CONTROLLER_ERROR,
101 MGMT_EV_INDEX_ADDED,
102 MGMT_EV_INDEX_REMOVED,
103 MGMT_EV_NEW_SETTINGS,
104 MGMT_EV_CLASS_OF_DEV_CHANGED,
105 MGMT_EV_LOCAL_NAME_CHANGED,
106 MGMT_EV_NEW_LINK_KEY,
107 MGMT_EV_NEW_LONG_TERM_KEY,
108 MGMT_EV_DEVICE_CONNECTED,
109 MGMT_EV_DEVICE_DISCONNECTED,
110 MGMT_EV_CONNECT_FAILED,
111 MGMT_EV_PIN_CODE_REQUEST,
112 MGMT_EV_USER_CONFIRM_REQUEST,
113 MGMT_EV_USER_PASSKEY_REQUEST,
114 MGMT_EV_AUTH_FAILED,
115 MGMT_EV_DEVICE_FOUND,
116 MGMT_EV_DISCOVERING,
117 MGMT_EV_DEVICE_BLOCKED,
118 MGMT_EV_DEVICE_UNBLOCKED,
119 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300120 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800121 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700122 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200123 MGMT_EV_DEVICE_ADDED,
124 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300125 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200126 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd3896b2014-07-02 21:30:55 +0200127 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200128 MGMT_EV_NEW_CONFIG_OPTIONS,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200129};
130
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800131#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200132
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200133struct pending_cmd {
134 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200135 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200136 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100137 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200138 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300140 void *user_data;
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +0200141 void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200142};
143
Johan Hedbergca69b792011-11-11 18:10:00 +0200144/* HCI to MGMT error code conversion table */
145static u8 mgmt_status_table[] = {
146 MGMT_STATUS_SUCCESS,
147 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
148 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
149 MGMT_STATUS_FAILED, /* Hardware Failure */
150 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
151 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200152 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200153 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
154 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
155 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
156 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
157 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
158 MGMT_STATUS_BUSY, /* Command Disallowed */
159 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
160 MGMT_STATUS_REJECTED, /* Rejected Security */
161 MGMT_STATUS_REJECTED, /* Rejected Personal */
162 MGMT_STATUS_TIMEOUT, /* Host Timeout */
163 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
164 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
165 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
166 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
167 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
168 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
169 MGMT_STATUS_BUSY, /* Repeated Attempts */
170 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
171 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
172 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
173 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
174 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
175 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
176 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
177 MGMT_STATUS_FAILED, /* Unspecified Error */
178 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
179 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
180 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
181 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
182 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
183 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
184 MGMT_STATUS_FAILED, /* Unit Link Key Used */
185 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
186 MGMT_STATUS_TIMEOUT, /* Instant Passed */
187 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
188 MGMT_STATUS_FAILED, /* Transaction Collision */
189 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
190 MGMT_STATUS_REJECTED, /* QoS Rejected */
191 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
192 MGMT_STATUS_REJECTED, /* Insufficient Security */
193 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
194 MGMT_STATUS_BUSY, /* Role Switch Pending */
195 MGMT_STATUS_FAILED, /* Slot Violation */
196 MGMT_STATUS_FAILED, /* Role Switch Failed */
197 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
198 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
199 MGMT_STATUS_BUSY, /* Host Busy Pairing */
200 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
201 MGMT_STATUS_BUSY, /* Controller Busy */
202 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
203 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
204 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
205 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
206 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
207};
208
209static u8 mgmt_status(u8 hci_status)
210{
211 if (hci_status < ARRAY_SIZE(mgmt_status_table))
212 return mgmt_status_table[hci_status];
213
214 return MGMT_STATUS_FAILED;
215}
216
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200217static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len,
218 struct sock *skip_sk)
219{
220 struct sk_buff *skb;
221 struct mgmt_hdr *hdr;
222
223 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
224 if (!skb)
225 return -ENOMEM;
226
227 hdr = (void *) skb_put(skb, sizeof(*hdr));
228 hdr->opcode = cpu_to_le16(event);
229 if (hdev)
230 hdr->index = cpu_to_le16(hdev->id);
231 else
232 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
233 hdr->len = cpu_to_le16(data_len);
234
235 if (data)
236 memcpy(skb_put(skb, data_len), data, data_len);
237
238 /* Time stamp */
239 __net_timestamp(skb);
240
241 hci_send_to_control(skb, skip_sk);
242 kfree_skb(skb);
243
244 return 0;
245}
246
Szymon Janc4e51eae2011-02-25 19:05:48 +0100247static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200248{
249 struct sk_buff *skb;
250 struct mgmt_hdr *hdr;
251 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300252 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200253
Szymon Janc34eb5252011-02-28 14:10:08 +0100254 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200255
Andre Guedes790eff42012-06-07 19:05:46 -0300256 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200257 if (!skb)
258 return -ENOMEM;
259
260 hdr = (void *) skb_put(skb, sizeof(*hdr));
261
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700262 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100263 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200264 hdr->len = cpu_to_le16(sizeof(*ev));
265
266 ev = (void *) skb_put(skb, sizeof(*ev));
267 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200268 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200269
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300270 err = sock_queue_rcv_skb(sk, skb);
271 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200272 kfree_skb(skb);
273
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300274 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200275}
276
Johan Hedbergaee9b212012-02-18 15:07:59 +0200277static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300278 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200279{
280 struct sk_buff *skb;
281 struct mgmt_hdr *hdr;
282 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300283 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200284
285 BT_DBG("sock %p", sk);
286
Andre Guedes790eff42012-06-07 19:05:46 -0300287 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200288 if (!skb)
289 return -ENOMEM;
290
291 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200292
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700293 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100294 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200295 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200296
Johan Hedberga38528f2011-01-22 06:46:43 +0200297 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200298 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200299 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100300
301 if (rp)
302 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200303
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300304 err = sock_queue_rcv_skb(sk, skb);
305 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200306 kfree_skb(skb);
307
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100308 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200309}
310
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300311static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
312 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200313{
314 struct mgmt_rp_read_version rp;
315
316 BT_DBG("sock %p", sk);
317
318 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700319 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200320
Johan Hedbergaee9b212012-02-18 15:07:59 +0200321 return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300322 sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200323}
324
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300325static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
326 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200327{
328 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200329 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
330 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200331 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200332 size_t rp_size;
333 int i, err;
334
335 BT_DBG("sock %p", sk);
336
337 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
338
339 rp = kmalloc(rp_size, GFP_KERNEL);
340 if (!rp)
341 return -ENOMEM;
342
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700343 rp->num_commands = cpu_to_le16(num_commands);
344 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200345
346 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
347 put_unaligned_le16(mgmt_commands[i], opcode);
348
349 for (i = 0; i < num_events; i++, opcode++)
350 put_unaligned_le16(mgmt_events[i], opcode);
351
Johan Hedbergaee9b212012-02-18 15:07:59 +0200352 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353 rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200354 kfree(rp);
355
356 return err;
357}
358
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300359static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
360 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200361{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200362 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200363 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200364 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200365 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300366 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200367
368 BT_DBG("sock %p", sk);
369
370 read_lock(&hci_dev_list_lock);
371
372 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300373 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200374 if (d->dev_type == HCI_BREDR &&
375 !test_bit(HCI_UNCONFIGURED, &d->dev_flags))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700376 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200377 }
378
Johan Hedberga38528f2011-01-22 06:46:43 +0200379 rp_len = sizeof(*rp) + (2 * count);
380 rp = kmalloc(rp_len, GFP_ATOMIC);
381 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100382 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200383 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100384 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200385
Johan Hedberg476e44c2012-10-19 20:10:46 +0300386 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200387 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200388 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200389 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200390 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200391 continue;
392
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200393 /* Devices marked as raw-only are neither configured
394 * nor unconfigured controllers.
395 */
396 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700397 continue;
398
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200399 if (d->dev_type == HCI_BREDR &&
400 !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700401 rp->index[count++] = cpu_to_le16(d->id);
402 BT_DBG("Added hci%u", d->id);
403 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 }
405
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 rp->num_controllers = cpu_to_le16(count);
407 rp_len = sizeof(*rp) + (2 * count);
408
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409 read_unlock(&hci_dev_list_lock);
410
Johan Hedbergaee9b212012-02-18 15:07:59 +0200411 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300412 rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200413
Johan Hedberga38528f2011-01-22 06:46:43 +0200414 kfree(rp);
415
416 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417}
418
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200419static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
420 void *data, u16 data_len)
421{
422 struct mgmt_rp_read_unconf_index_list *rp;
423 struct hci_dev *d;
424 size_t rp_len;
425 u16 count;
426 int err;
427
428 BT_DBG("sock %p", sk);
429
430 read_lock(&hci_dev_list_lock);
431
432 count = 0;
433 list_for_each_entry(d, &hci_dev_list, list) {
434 if (d->dev_type == HCI_BREDR &&
435 test_bit(HCI_UNCONFIGURED, &d->dev_flags))
436 count++;
437 }
438
439 rp_len = sizeof(*rp) + (2 * count);
440 rp = kmalloc(rp_len, GFP_ATOMIC);
441 if (!rp) {
442 read_unlock(&hci_dev_list_lock);
443 return -ENOMEM;
444 }
445
446 count = 0;
447 list_for_each_entry(d, &hci_dev_list, list) {
448 if (test_bit(HCI_SETUP, &d->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +0200449 test_bit(HCI_CONFIG, &d->dev_flags) ||
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200450 test_bit(HCI_USER_CHANNEL, &d->dev_flags))
451 continue;
452
453 /* Devices marked as raw-only are neither configured
454 * nor unconfigured controllers.
455 */
456 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
457 continue;
458
459 if (d->dev_type == HCI_BREDR &&
460 test_bit(HCI_UNCONFIGURED, &d->dev_flags)) {
461 rp->index[count++] = cpu_to_le16(d->id);
462 BT_DBG("Added hci%u", d->id);
463 }
464 }
465
466 rp->num_controllers = cpu_to_le16(count);
467 rp_len = sizeof(*rp) + (2 * count);
468
469 read_unlock(&hci_dev_list_lock);
470
471 err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST,
472 0, rp, rp_len);
473
474 kfree(rp);
475
476 return err;
477}
478
Marcel Holtmanndbece372014-07-04 18:11:55 +0200479static bool is_configured(struct hci_dev *hdev)
480{
481 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
482 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
483 return false;
484
485 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
486 !bacmp(&hdev->public_addr, BDADDR_ANY))
487 return false;
488
489 return true;
490}
491
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200492static __le32 get_missing_options(struct hci_dev *hdev)
493{
494 u32 options = 0;
495
Marcel Holtmanndbece372014-07-04 18:11:55 +0200496 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
497 !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200498 options |= MGMT_OPTION_EXTERNAL_CONFIG;
499
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200500 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
501 !bacmp(&hdev->public_addr, BDADDR_ANY))
502 options |= MGMT_OPTION_PUBLIC_ADDRESS;
503
504 return cpu_to_le32(options);
505}
506
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200507static int new_options(struct hci_dev *hdev, struct sock *skip)
508{
509 __le32 options = get_missing_options(hdev);
510
511 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
512 sizeof(options), skip);
513}
514
Marcel Holtmanndbece372014-07-04 18:11:55 +0200515static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
516{
517 __le32 options = get_missing_options(hdev);
518
519 return cmd_complete(sk, hdev->id, opcode, 0, &options,
520 sizeof(options));
521}
522
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200523static int read_config_info(struct sock *sk, struct hci_dev *hdev,
524 void *data, u16 data_len)
525{
526 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200527 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200528
529 BT_DBG("sock %p %s", sk, hdev->name);
530
531 hci_dev_lock(hdev);
532
533 memset(&rp, 0, sizeof(rp));
534 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200535
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
537 options |= MGMT_OPTION_EXTERNAL_CONFIG;
538
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200539 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 options |= MGMT_OPTION_PUBLIC_ADDRESS;
541
542 rp.supported_options = cpu_to_le32(options);
543 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200544
545 hci_dev_unlock(hdev);
546
547 return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp,
548 sizeof(rp));
549}
550
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200551static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200552{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200553 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200554
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200555 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300556 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800557 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300558 settings |= MGMT_SETTING_CONNECTABLE;
559 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200560
Andre Guedesed3fa312012-07-24 15:03:46 -0300561 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500562 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
563 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200564 settings |= MGMT_SETTING_BREDR;
565 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700566
567 if (lmp_ssp_capable(hdev)) {
568 settings |= MGMT_SETTING_SSP;
569 settings |= MGMT_SETTING_HS;
570 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800571
Marcel Holtmann5afeac12014-01-10 02:07:27 -0800572 if (lmp_sc_capable(hdev) ||
Marcel Holtmann111902f2014-06-21 04:53:17 +0200573 test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800574 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700575 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100576
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300577 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200578 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300579 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300580 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200581 settings |= MGMT_SETTING_PRIVACY;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300582 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200583
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200584 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
585 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586 settings |= MGMT_SETTING_CONFIGURATION;
587
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200588 return settings;
589}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_current_settings(struct hci_dev *hdev)
592{
593 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200594
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200595 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100596 settings |= MGMT_SETTING_POWERED;
597
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200598 if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200599 settings |= MGMT_SETTING_CONNECTABLE;
600
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500601 if (test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
602 settings |= MGMT_SETTING_FAST_CONNECTABLE;
603
Johan Hedberg5e5282b2012-02-21 16:01:30 +0200604 if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200605 settings |= MGMT_SETTING_DISCOVERABLE;
606
Johan Hedbergb6ae8452014-07-30 09:22:22 +0300607 if (test_bit(HCI_BONDABLE, &hdev->dev_flags))
Johan Hedbergb2939472014-07-30 09:22:23 +0300608 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200609
Johan Hedberg56f87902013-10-02 13:43:13 +0300610 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200611 settings |= MGMT_SETTING_BREDR;
612
Johan Hedberg06199cf2012-02-22 16:37:11 +0200613 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200614 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200615
Johan Hedberg47990ea2012-02-22 11:58:37 +0200616 if (test_bit(HCI_LINK_SECURITY, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200617 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200618
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200619 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200620 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200621
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200622 if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags))
623 settings |= MGMT_SETTING_HS;
624
Johan Hedbergf3d3444a2013-10-05 12:01:04 +0200625 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300626 settings |= MGMT_SETTING_ADVERTISING;
627
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800628 if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
629 settings |= MGMT_SETTING_SECURE_CONN;
630
Johan Hedberg0663b292014-06-24 13:15:50 +0300631 if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800632 settings |= MGMT_SETTING_DEBUG_KEYS;
633
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200634 if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
635 settings |= MGMT_SETTING_PRIVACY;
636
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200637 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200638}
639
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300640#define PNP_INFO_SVCLASS_ID 0x1200
641
Johan Hedberg213202e2013-01-27 00:31:33 +0200642static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
643{
644 u8 *ptr = data, *uuids_start = NULL;
645 struct bt_uuid *uuid;
646
647 if (len < 4)
648 return ptr;
649
650 list_for_each_entry(uuid, &hdev->uuids, list) {
651 u16 uuid16;
652
653 if (uuid->size != 16)
654 continue;
655
656 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
657 if (uuid16 < 0x1100)
658 continue;
659
660 if (uuid16 == PNP_INFO_SVCLASS_ID)
661 continue;
662
663 if (!uuids_start) {
664 uuids_start = ptr;
665 uuids_start[0] = 1;
666 uuids_start[1] = EIR_UUID16_ALL;
667 ptr += 2;
668 }
669
670 /* Stop if not enough space to put next UUID */
671 if ((ptr - data) + sizeof(u16) > len) {
672 uuids_start[1] = EIR_UUID16_SOME;
673 break;
674 }
675
676 *ptr++ = (uuid16 & 0x00ff);
677 *ptr++ = (uuid16 & 0xff00) >> 8;
678 uuids_start[0] += sizeof(uuid16);
679 }
680
681 return ptr;
682}
683
Johan Hedbergcdf19632013-01-27 00:31:34 +0200684static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
685{
686 u8 *ptr = data, *uuids_start = NULL;
687 struct bt_uuid *uuid;
688
689 if (len < 6)
690 return ptr;
691
692 list_for_each_entry(uuid, &hdev->uuids, list) {
693 if (uuid->size != 32)
694 continue;
695
696 if (!uuids_start) {
697 uuids_start = ptr;
698 uuids_start[0] = 1;
699 uuids_start[1] = EIR_UUID32_ALL;
700 ptr += 2;
701 }
702
703 /* Stop if not enough space to put next UUID */
704 if ((ptr - data) + sizeof(u32) > len) {
705 uuids_start[1] = EIR_UUID32_SOME;
706 break;
707 }
708
709 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
710 ptr += sizeof(u32);
711 uuids_start[0] += sizeof(u32);
712 }
713
714 return ptr;
715}
716
Johan Hedbergc00d5752013-01-27 00:31:35 +0200717static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
718{
719 u8 *ptr = data, *uuids_start = NULL;
720 struct bt_uuid *uuid;
721
722 if (len < 18)
723 return ptr;
724
725 list_for_each_entry(uuid, &hdev->uuids, list) {
726 if (uuid->size != 128)
727 continue;
728
729 if (!uuids_start) {
730 uuids_start = ptr;
731 uuids_start[0] = 1;
732 uuids_start[1] = EIR_UUID128_ALL;
733 ptr += 2;
734 }
735
736 /* Stop if not enough space to put next UUID */
737 if ((ptr - data) + 16 > len) {
738 uuids_start[1] = EIR_UUID128_SOME;
739 break;
740 }
741
742 memcpy(ptr, uuid->uuid, 16);
743 ptr += 16;
744 uuids_start[0] += 16;
745 }
746
747 return ptr;
748}
749
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300750static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
751{
752 struct pending_cmd *cmd;
753
754 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
755 if (cmd->opcode == opcode)
756 return cmd;
757 }
758
759 return NULL;
760}
761
Johan Hedberg95868422014-06-28 17:54:07 +0300762static struct pending_cmd *mgmt_pending_find_data(u16 opcode,
763 struct hci_dev *hdev,
764 const void *data)
765{
766 struct pending_cmd *cmd;
767
768 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
769 if (cmd->user_data != data)
770 continue;
771 if (cmd->opcode == opcode)
772 return cmd;
773 }
774
775 return NULL;
776}
777
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700778static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
779{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700780 u8 ad_len = 0;
781 size_t name_len;
782
783 name_len = strlen(hdev->dev_name);
784 if (name_len > 0) {
785 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
786
787 if (name_len > max_len) {
788 name_len = max_len;
789 ptr[1] = EIR_NAME_SHORT;
790 } else
791 ptr[1] = EIR_NAME_COMPLETE;
792
793 ptr[0] = name_len + 1;
794
795 memcpy(ptr + 2, hdev->dev_name, name_len);
796
797 ad_len += (name_len + 2);
798 ptr += (name_len + 2);
799 }
800
801 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700802}
803
804static void update_scan_rsp_data(struct hci_request *req)
805{
806 struct hci_dev *hdev = req->hdev;
807 struct hci_cp_le_set_scan_rsp_data cp;
808 u8 len;
809
Johan Hedberg7751ef12013-10-19 23:38:15 +0300810 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700811 return;
812
813 memset(&cp, 0, sizeof(cp));
814
815 len = create_scan_rsp_data(hdev, cp.data);
816
Johan Hedbergeb438b52013-10-16 15:31:07 +0300817 if (hdev->scan_rsp_data_len == len &&
818 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700819 return;
820
Johan Hedbergeb438b52013-10-16 15:31:07 +0300821 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
822 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700823
824 cp.length = len;
825
826 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
827}
828
Johan Hedberg9a43e252013-10-20 19:00:07 +0300829static u8 get_adv_discov_flags(struct hci_dev *hdev)
830{
831 struct pending_cmd *cmd;
832
833 /* If there's a pending mgmt command the flags will not yet have
834 * their final values, so check for this first.
835 */
836 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
837 if (cmd) {
838 struct mgmt_mode *cp = cmd->param;
839 if (cp->val == 0x01)
840 return LE_AD_GENERAL;
841 else if (cp->val == 0x02)
842 return LE_AD_LIMITED;
843 } else {
844 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
845 return LE_AD_LIMITED;
846 else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
847 return LE_AD_GENERAL;
848 }
849
850 return 0;
851}
852
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700853static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700854{
855 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700856
Johan Hedberg9a43e252013-10-20 19:00:07 +0300857 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700858
Johan Hedberge8340042014-01-30 11:16:50 -0800859 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700860 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700861
862 if (flags) {
863 BT_DBG("adv flags 0x%02x", flags);
864
865 ptr[0] = 2;
866 ptr[1] = EIR_FLAGS;
867 ptr[2] = flags;
868
869 ad_len += 3;
870 ptr += 3;
871 }
872
873 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
874 ptr[0] = 2;
875 ptr[1] = EIR_TX_POWER;
876 ptr[2] = (u8) hdev->adv_tx_power;
877
878 ad_len += 3;
879 ptr += 3;
880 }
881
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700882 return ad_len;
883}
884
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700885static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700886{
887 struct hci_dev *hdev = req->hdev;
888 struct hci_cp_le_set_adv_data cp;
889 u8 len;
890
Johan Hedberg10994ce2013-10-19 23:38:16 +0300891 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700892 return;
893
894 memset(&cp, 0, sizeof(cp));
895
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700896 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700897
898 if (hdev->adv_data_len == len &&
899 memcmp(cp.data, hdev->adv_data, len) == 0)
900 return;
901
902 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
903 hdev->adv_data_len = len;
904
905 cp.length = len;
906
907 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
908}
909
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300910int mgmt_update_adv_data(struct hci_dev *hdev)
911{
912 struct hci_request req;
913
914 hci_req_init(&req, hdev);
915 update_adv_data(&req);
916
917 return hci_req_run(&req, NULL);
918}
919
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300920static void create_eir(struct hci_dev *hdev, u8 *data)
921{
922 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300923 size_t name_len;
924
925 name_len = strlen(hdev->dev_name);
926
927 if (name_len > 0) {
928 /* EIR Data type */
929 if (name_len > 48) {
930 name_len = 48;
931 ptr[1] = EIR_NAME_SHORT;
932 } else
933 ptr[1] = EIR_NAME_COMPLETE;
934
935 /* EIR Data length */
936 ptr[0] = name_len + 1;
937
938 memcpy(ptr + 2, hdev->dev_name, name_len);
939
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300940 ptr += (name_len + 2);
941 }
942
Johan Hedbergbbaf4442012-11-08 01:22:59 +0100943 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700944 ptr[0] = 2;
945 ptr[1] = EIR_TX_POWER;
946 ptr[2] = (u8) hdev->inq_tx_power;
947
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -0700948 ptr += 3;
949 }
950
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700951 if (hdev->devid_source > 0) {
952 ptr[0] = 9;
953 ptr[1] = EIR_DEVICE_ID;
954
955 put_unaligned_le16(hdev->devid_source, ptr + 2);
956 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
957 put_unaligned_le16(hdev->devid_product, ptr + 6);
958 put_unaligned_le16(hdev->devid_version, ptr + 8);
959
Marcel Holtmann2b9be132012-03-11 19:32:12 -0700960 ptr += 10;
961 }
962
Johan Hedberg213202e2013-01-27 00:31:33 +0200963 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +0200964 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +0200965 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300966}
967
Johan Hedberg890ea892013-03-15 17:06:52 -0500968static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300969{
Johan Hedberg890ea892013-03-15 17:06:52 -0500970 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300971 struct hci_cp_write_eir cp;
972
Johan Hedberg504c8dc2012-02-23 13:30:41 +0200973 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500974 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +0200975
Johan Hedberg976eb202012-10-24 21:12:01 +0300976 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -0500977 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300978
Johan Hedberg84bde9d2012-01-25 14:21:06 +0200979 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500980 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300981
Johan Hedberga8b2d5c2012-01-08 23:11:15 +0200982 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -0500983 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300984
985 memset(&cp, 0, sizeof(cp));
986
987 create_eir(hdev, cp.data);
988
989 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -0500990 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300991
992 memcpy(hdev->eir, cp.data, sizeof(cp.data));
993
Johan Hedberg890ea892013-03-15 17:06:52 -0500994 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300995}
996
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200997static u8 get_service_classes(struct hci_dev *hdev)
998{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -0300999 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001000 u8 val = 0;
1001
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001002 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001003 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001004
1005 return val;
1006}
1007
Johan Hedberg890ea892013-03-15 17:06:52 -05001008static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001009{
Johan Hedberg890ea892013-03-15 17:06:52 -05001010 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001011 u8 cod[3];
1012
1013 BT_DBG("%s", hdev->name);
1014
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001015 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001016 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001017
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001018 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1019 return;
1020
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001021 if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05001022 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001023
1024 cod[0] = hdev->minor_class;
1025 cod[1] = hdev->major_class;
1026 cod[2] = get_service_classes(hdev);
1027
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001028 if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
1029 cod[1] |= 0x20;
1030
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001031 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001033
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001035}
1036
Johan Hedberga4858cb2014-02-25 19:56:31 +02001037static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001038{
1039 struct pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001040
1041 /* If there's a pending mgmt command the flag will not yet have
1042 * it's final value, so check for this first.
1043 */
1044 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1045 if (cmd) {
1046 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001047 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001048 }
1049
Johan Hedberga4858cb2014-02-25 19:56:31 +02001050 return test_bit(HCI_CONNECTABLE, &hdev->dev_flags);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001051}
1052
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001053static void disable_advertising(struct hci_request *req)
1054{
1055 u8 enable = 0x00;
1056
1057 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1058}
1059
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001060static void enable_advertising(struct hci_request *req)
1061{
1062 struct hci_dev *hdev = req->hdev;
1063 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001064 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001065 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001066
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001067 if (hci_conn_num(hdev, LE_LINK) > 0)
1068 return;
1069
1070 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
1071 disable_advertising(req);
1072
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001073 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001074 * hci_update_random_address knows that it's safe to go ahead
1075 * and write a new random address. The flag will be set back on
1076 * as soon as the SET_ADV_ENABLE HCI command completes.
1077 */
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001078 clear_bit(HCI_LE_ADV, &hdev->dev_flags);
Johan Hedberg8d972502014-02-28 12:54:14 +02001079
Johan Hedberga4858cb2014-02-25 19:56:31 +02001080 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001081
Johan Hedberga4858cb2014-02-25 19:56:31 +02001082 /* Set require_privacy to true only when non-connectable
1083 * advertising is used. In that case it is fine to use a
1084 * non-resolvable private address.
1085 */
1086 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001087 return;
1088
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001089 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001090 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1091 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001092 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001093 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001094 cp.channel_map = hdev->le_adv_channel_map;
1095
1096 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1097
1098 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1099}
1100
Johan Hedberg7d785252011-12-15 00:47:39 +02001101static void service_cache_off(struct work_struct *work)
1102{
1103 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001104 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001105 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001106
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02001107 if (!test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
Johan Hedberg7d785252011-12-15 00:47:39 +02001108 return;
1109
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 hci_req_init(&req, hdev);
1111
Johan Hedberg7d785252011-12-15 00:47:39 +02001112 hci_dev_lock(hdev);
1113
Johan Hedberg890ea892013-03-15 17:06:52 -05001114 update_eir(&req);
1115 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001116
1117 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001118
1119 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001120}
1121
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001122static void rpa_expired(struct work_struct *work)
1123{
1124 struct hci_dev *hdev = container_of(work, struct hci_dev,
1125 rpa_expired.work);
1126 struct hci_request req;
1127
1128 BT_DBG("");
1129
1130 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
1131
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001132 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001133 return;
1134
1135 /* The generation of a new RPA and programming it into the
1136 * controller happens in the enable_advertising() function.
1137 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001138 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001139 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001140 hci_req_run(&req, NULL);
1141}
1142
Johan Hedberg6a919082012-02-28 06:17:26 +02001143static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001144{
Johan Hedberg4f87da82012-03-02 19:55:56 +02001145 if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags))
Johan Hedberg6a919082012-02-28 06:17:26 +02001146 return;
1147
Johan Hedberg4f87da82012-03-02 19:55:56 +02001148 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001149 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001150
Johan Hedberg4f87da82012-03-02 19:55:56 +02001151 /* Non-mgmt controlled devices get this bit set
1152 * implicitly so that pairing works for them, however
1153 * for mgmt we require user-space to explicitly enable
1154 * it
1155 */
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001156 clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedberg7d785252011-12-15 00:47:39 +02001157}
1158
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001159static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001160 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001161{
1162 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001163
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001164 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001165
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001166 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001167
Johan Hedberg03811012010-12-08 00:21:06 +02001168 memset(&rp, 0, sizeof(rp));
1169
Johan Hedberg03811012010-12-08 00:21:06 +02001170 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001171
1172 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001173 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001174
1175 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1176 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1177
1178 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001179
1180 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001181 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001182
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001183 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001184
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001185 return cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001186 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001187}
1188
1189static void mgmt_pending_free(struct pending_cmd *cmd)
1190{
1191 sock_put(cmd->sk);
1192 kfree(cmd->param);
1193 kfree(cmd);
1194}
1195
1196static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001197 struct hci_dev *hdev, void *data,
1198 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001199{
1200 struct pending_cmd *cmd;
1201
Johan Hedbergfca20012014-06-28 17:54:05 +03001202 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001203 if (!cmd)
1204 return NULL;
1205
1206 cmd->opcode = opcode;
1207 cmd->index = hdev->id;
1208
Johan Hedberg323b0b82014-12-05 13:36:01 +02001209 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001210 if (!cmd->param) {
1211 kfree(cmd);
1212 return NULL;
1213 }
1214
Johan Hedberg323b0b82014-12-05 13:36:01 +02001215 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001216
1217 cmd->sk = sk;
1218 sock_hold(sk);
1219
1220 list_add(&cmd->list, &hdev->mgmt_pending);
1221
1222 return cmd;
1223}
1224
1225static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001226 void (*cb)(struct pending_cmd *cmd,
1227 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001228 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001229{
Andre Guedesa3d09352013-02-01 11:21:30 -03001230 struct pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001231
Andre Guedesa3d09352013-02-01 11:21:30 -03001232 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001233 if (opcode > 0 && cmd->opcode != opcode)
1234 continue;
1235
1236 cb(cmd, data);
1237 }
1238}
1239
Johan Hedberg03811012010-12-08 00:21:06 +02001240static void mgmt_pending_remove(struct pending_cmd *cmd)
1241{
1242 list_del(&cmd->list);
1243 mgmt_pending_free(cmd);
1244}
1245
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001246static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001247{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001248 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001249
Johan Hedbergaee9b212012-02-18 15:07:59 +02001250 return cmd_complete(sk, hdev->id, opcode, 0, &settings,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001251 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001252}
1253
Johan Hedberg8b064a32014-02-24 14:52:22 +02001254static void clean_up_hci_complete(struct hci_dev *hdev, u8 status)
1255{
1256 BT_DBG("%s status 0x%02x", hdev->name, status);
1257
Johan Hedberga3172b72014-02-28 09:33:44 +02001258 if (hci_conn_count(hdev) == 0) {
1259 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001261 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001262}
1263
Johan Hedberg23a48092014-07-08 16:05:06 +03001264static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001265{
1266 struct hci_dev *hdev = req->hdev;
1267 struct hci_cp_remote_name_req_cancel cp;
1268 struct inquiry_entry *e;
1269
1270 switch (hdev->discovery.state) {
1271 case DISCOVERY_FINDING:
1272 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1273 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1274 } else {
1275 cancel_delayed_work(&hdev->le_scan_disable);
1276 hci_req_add_le_scan_disable(req);
1277 }
1278
Johan Hedberg23a48092014-07-08 16:05:06 +03001279 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001280
1281 case DISCOVERY_RESOLVING:
1282 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1283 NAME_PENDING);
1284 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001285 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001286
1287 bacpy(&cp.bdaddr, &e->data.bdaddr);
1288 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1289 &cp);
1290
Johan Hedberg23a48092014-07-08 16:05:06 +03001291 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001292
1293 default:
1294 /* Passive scanning */
Johan Hedberg23a48092014-07-08 16:05:06 +03001295 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001296 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001297 return true;
1298 }
1299
Johan Hedberg21a60d32014-06-10 14:05:58 +03001300 break;
1301 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001302
1303 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001304}
1305
Johan Hedberg8b064a32014-02-24 14:52:22 +02001306static int clean_up_hci_state(struct hci_dev *hdev)
1307{
1308 struct hci_request req;
1309 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001310 bool discov_stopped;
1311 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001312
1313 hci_req_init(&req, hdev);
1314
1315 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1316 test_bit(HCI_PSCAN, &hdev->flags)) {
1317 u8 scan = 0x00;
1318 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1319 }
1320
Johan Hedberg73e082f2014-07-08 15:07:51 +03001321 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001322 disable_advertising(&req);
1323
Johan Hedberg23a48092014-07-08 16:05:06 +03001324 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325
1326 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1327 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001328 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001329
Johan Hedbergc9910d02014-02-27 14:35:12 +02001330 switch (conn->state) {
1331 case BT_CONNECTED:
1332 case BT_CONFIG:
1333 dc.handle = cpu_to_le16(conn->handle);
1334 dc.reason = 0x15; /* Terminated due to Power Off */
1335 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1336 break;
1337 case BT_CONNECT:
1338 if (conn->type == LE_LINK)
1339 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1340 0, NULL);
1341 else if (conn->type == ACL_LINK)
1342 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1343 6, &conn->dst);
1344 break;
1345 case BT_CONNECT2:
1346 bacpy(&rej.bdaddr, &conn->dst);
1347 rej.reason = 0x15; /* Terminated due to Power Off */
1348 if (conn->type == ACL_LINK)
1349 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1350 sizeof(rej), &rej);
1351 else if (conn->type == SCO_LINK)
1352 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1353 sizeof(rej), &rej);
1354 break;
1355 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001356 }
1357
Johan Hedberg23a48092014-07-08 16:05:06 +03001358 err = hci_req_run(&req, clean_up_hci_complete);
1359 if (!err && discov_stopped)
1360 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1361
1362 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001363}
1364
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001365static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001366 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001367{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001368 struct mgmt_mode *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001369 struct pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001370 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001371
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001372 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001373
Johan Hedberga7e80f22013-01-09 16:05:19 +02001374 if (cp->val != 0x00 && cp->val != 0x01)
1375 return cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1376 MGMT_STATUS_INVALID_PARAMS);
1377
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001378 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001379
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001380 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
1381 err = cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1382 MGMT_STATUS_BUSY);
1383 goto failed;
1384 }
1385
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001386 if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
1387 cancel_delayed_work(&hdev->power_off);
1388
1389 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001390 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1391 data, len);
1392 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001393 goto failed;
1394 }
1395 }
1396
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001397 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001398 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001399 goto failed;
1400 }
1401
Johan Hedberg03811012010-12-08 00:21:06 +02001402 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1403 if (!cmd) {
1404 err = -ENOMEM;
1405 goto failed;
1406 }
1407
Johan Hedberg8b064a32014-02-24 14:52:22 +02001408 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001409 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001410 err = 0;
1411 } else {
1412 /* Disconnect connections, stop scans, etc */
1413 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001414 if (!err)
1415 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1416 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001417
Johan Hedberg8b064a32014-02-24 14:52:22 +02001418 /* ENODATA means there were no HCI commands queued */
1419 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001420 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1422 err = 0;
1423 }
1424 }
Johan Hedberg03811012010-12-08 00:21:06 +02001425
1426failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001427 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001428 return err;
1429}
1430
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001431static int new_settings(struct hci_dev *hdev, struct sock *skip)
1432{
1433 __le32 ev;
1434
1435 ev = cpu_to_le32(get_current_settings(hdev));
1436
1437 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1438}
1439
Johan Hedberg91a668b2014-07-09 13:28:26 +03001440int mgmt_new_settings(struct hci_dev *hdev)
1441{
1442 return new_settings(hdev, NULL);
1443}
1444
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001445struct cmd_lookup {
1446 struct sock *sk;
1447 struct hci_dev *hdev;
1448 u8 mgmt_status;
1449};
1450
1451static void settings_rsp(struct pending_cmd *cmd, void *data)
1452{
1453 struct cmd_lookup *match = data;
1454
1455 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1456
1457 list_del(&cmd->list);
1458
1459 if (match->sk == NULL) {
1460 match->sk = cmd->sk;
1461 sock_hold(match->sk);
1462 }
1463
1464 mgmt_pending_free(cmd);
1465}
1466
1467static void cmd_status_rsp(struct pending_cmd *cmd, void *data)
1468{
1469 u8 *status = data;
1470
1471 cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
1472 mgmt_pending_remove(cmd);
1473}
1474
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001475static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
1476{
1477 if (cmd->cmd_complete) {
1478 u8 *status = data;
1479
1480 cmd->cmd_complete(cmd, *status);
1481 mgmt_pending_remove(cmd);
1482
1483 return;
1484 }
1485
1486 cmd_status_rsp(cmd, data);
1487}
1488
Johan Hedbergf5818c22014-12-05 13:36:02 +02001489static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
1490{
1491 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1492 cmd->param_len);
1493}
1494
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001495static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
1496{
1497 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
1498 sizeof(struct mgmt_addr_info));
1499}
1500
Johan Hedberge6fe7982013-10-02 15:45:22 +03001501static u8 mgmt_bredr_support(struct hci_dev *hdev)
1502{
1503 if (!lmp_bredr_capable(hdev))
1504 return MGMT_STATUS_NOT_SUPPORTED;
1505 else if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1506 return MGMT_STATUS_REJECTED;
1507 else
1508 return MGMT_STATUS_SUCCESS;
1509}
1510
1511static u8 mgmt_le_support(struct hci_dev *hdev)
1512{
1513 if (!lmp_le_capable(hdev))
1514 return MGMT_STATUS_NOT_SUPPORTED;
1515 else if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
1516 return MGMT_STATUS_REJECTED;
1517 else
1518 return MGMT_STATUS_SUCCESS;
1519}
1520
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001521static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
1522{
1523 struct pending_cmd *cmd;
1524 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001525 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001526 bool changed;
1527
1528 BT_DBG("status 0x%02x", status);
1529
1530 hci_dev_lock(hdev);
1531
1532 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1533 if (!cmd)
1534 goto unlock;
1535
1536 if (status) {
1537 u8 mgmt_err = mgmt_status(status);
1538 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001539 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001540 goto remove_cmd;
1541 }
1542
1543 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001544 if (cp->val) {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001545 changed = !test_and_set_bit(HCI_DISCOVERABLE,
1546 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001547
1548 if (hdev->discov_timeout > 0) {
1549 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1550 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1551 to);
1552 }
1553 } else {
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001554 changed = test_and_clear_bit(HCI_DISCOVERABLE,
1555 &hdev->dev_flags);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001556 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001557
1558 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1559
1560 if (changed)
1561 new_settings(hdev, cmd->sk);
1562
Marcel Holtmann970ba522013-10-15 06:33:57 -07001563 /* When the discoverable mode gets changed, make sure
1564 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001565 * bit correctly set. Also update page scan based on whitelist
1566 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001567 */
1568 hci_req_init(&req, hdev);
Johan Hedberg432df052014-08-01 11:13:31 +03001569 hci_update_page_scan(hdev, &req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001570 update_class(&req);
1571 hci_req_run(&req, NULL);
1572
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001573remove_cmd:
1574 mgmt_pending_remove(cmd);
1575
1576unlock:
1577 hci_dev_unlock(hdev);
1578}
1579
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001580static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001581 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001582{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001583 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg03811012010-12-08 00:21:06 +02001584 struct pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001585 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001586 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001587 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001588 int err;
1589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001590 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001591
Johan Hedberg9a43e252013-10-20 19:00:07 +03001592 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1593 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001594 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Johan Hedberg9a43e252013-10-20 19:00:07 +03001595 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001596
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001597 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga7e80f22013-01-09 16:05:19 +02001598 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1599 MGMT_STATUS_INVALID_PARAMS);
1600
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001601 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001602
1603 /* Disabling discoverable requires that no timeout is set,
1604 * and enabling limited discoverable requires a timeout.
1605 */
1606 if ((cp->val == 0x00 && timeout > 0) ||
1607 (cp->val == 0x02 && timeout == 0))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001608 return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001609 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001610
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001611 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001612
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001613 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001614 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001615 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001616 goto failed;
1617 }
1618
1619 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001620 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001621 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001622 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001623 goto failed;
1624 }
1625
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001626 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001627 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001628 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001629 goto failed;
1630 }
1631
1632 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001633 bool changed = false;
1634
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001635 /* Setting limited discoverable when powered off is
1636 * not a valid operation since it requires a timeout
1637 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1638 */
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001639 if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
1640 change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1641 changed = true;
1642 }
1643
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001644 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001645 if (err < 0)
1646 goto failed;
1647
1648 if (changed)
1649 err = new_settings(hdev, sk);
1650
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001651 goto failed;
1652 }
1653
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001654 /* If the current mode is the same, then just update the timeout
1655 * value with the new value. And if only the timeout gets updated,
1656 * then no need for any HCI transactions.
1657 */
1658 if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
1659 (cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
1660 &hdev->dev_flags)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001661 cancel_delayed_work(&hdev->discov_off);
1662 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001663
Marcel Holtmann36261542013-10-15 08:28:51 -07001664 if (cp->val && hdev->discov_timeout > 0) {
1665 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001666 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001667 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001668 }
1669
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001670 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001671 goto failed;
1672 }
1673
1674 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1675 if (!cmd) {
1676 err = -ENOMEM;
1677 goto failed;
1678 }
1679
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001680 /* Cancel any potential discoverable timeout that might be
1681 * still active and store new timeout value. The arming of
1682 * the timeout happens in the complete handler.
1683 */
1684 cancel_delayed_work(&hdev->discov_off);
1685 hdev->discov_timeout = timeout;
1686
Johan Hedbergb456f872013-10-19 23:38:22 +03001687 /* Limited discoverable mode */
1688 if (cp->val == 0x02)
1689 set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1690 else
1691 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1692
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001693 hci_req_init(&req, hdev);
1694
Johan Hedberg9a43e252013-10-20 19:00:07 +03001695 /* The procedure for LE-only controllers is much simpler - just
1696 * update the advertising data.
1697 */
1698 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1699 goto update_ad;
1700
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001701 scan = SCAN_PAGE;
1702
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001703 if (cp->val) {
1704 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001705
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001706 if (cp->val == 0x02) {
1707 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001708 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001709 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1710 hci_cp.iac_lap[1] = 0x8b;
1711 hci_cp.iac_lap[2] = 0x9e;
1712 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1713 hci_cp.iac_lap[4] = 0x8b;
1714 hci_cp.iac_lap[5] = 0x9e;
1715 } else {
1716 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001717 hci_cp.num_iac = 1;
1718 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1719 hci_cp.iac_lap[1] = 0x8b;
1720 hci_cp.iac_lap[2] = 0x9e;
1721 }
1722
1723 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1724 (hci_cp.num_iac * 3) + 1, &hci_cp);
1725
1726 scan |= SCAN_INQUIRY;
1727 } else {
1728 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1729 }
1730
1731 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001732
Johan Hedberg9a43e252013-10-20 19:00:07 +03001733update_ad:
1734 update_adv_data(&req);
1735
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001736 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001737 if (err < 0)
1738 mgmt_pending_remove(cmd);
1739
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001740failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001741 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001742 return err;
1743}
1744
Johan Hedberg406d7802013-03-15 17:07:09 -05001745static void write_fast_connectable(struct hci_request *req, bool enable)
1746{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001747 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001748 struct hci_cp_write_page_scan_activity acp;
1749 u8 type;
1750
Johan Hedberg547003b2013-10-21 16:51:53 +03001751 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
1752 return;
1753
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001754 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1755 return;
1756
Johan Hedberg406d7802013-03-15 17:07:09 -05001757 if (enable) {
1758 type = PAGE_SCAN_TYPE_INTERLACED;
1759
1760 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001761 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001762 } else {
1763 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1764
1765 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001766 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001767 }
1768
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001769 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001770
Johan Hedbergbd98b992013-03-15 17:07:13 -05001771 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1772 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1773 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1774 sizeof(acp), &acp);
1775
1776 if (hdev->page_scan_type != type)
1777 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001778}
1779
Johan Hedberg2b76f452013-03-15 17:07:04 -05001780static void set_connectable_complete(struct hci_dev *hdev, u8 status)
1781{
1782 struct pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001783 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001784 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001785
1786 BT_DBG("status 0x%02x", status);
1787
1788 hci_dev_lock(hdev);
1789
1790 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1791 if (!cmd)
1792 goto unlock;
1793
Johan Hedberg37438c12013-10-14 16:20:05 +03001794 if (status) {
1795 u8 mgmt_err = mgmt_status(status);
1796 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
1797 goto remove_cmd;
1798 }
1799
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001800 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001801 if (cp->val) {
1802 conn_changed = !test_and_set_bit(HCI_CONNECTABLE,
1803 &hdev->dev_flags);
1804 discov_changed = false;
1805 } else {
1806 conn_changed = test_and_clear_bit(HCI_CONNECTABLE,
1807 &hdev->dev_flags);
1808 discov_changed = test_and_clear_bit(HCI_DISCOVERABLE,
1809 &hdev->dev_flags);
1810 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001811
Johan Hedberg2b76f452013-03-15 17:07:04 -05001812 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1813
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001814 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001815 new_settings(hdev, cmd->sk);
Johan Hedberg432df052014-08-01 11:13:31 +03001816 hci_update_page_scan(hdev, NULL);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001817 if (discov_changed)
1818 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001819 hci_update_background_scan(hdev);
1820 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001821
Johan Hedberg37438c12013-10-14 16:20:05 +03001822remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001823 mgmt_pending_remove(cmd);
1824
1825unlock:
1826 hci_dev_unlock(hdev);
1827}
1828
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001829static int set_connectable_update_settings(struct hci_dev *hdev,
1830 struct sock *sk, u8 val)
1831{
1832 bool changed = false;
1833 int err;
1834
1835 if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
1836 changed = true;
1837
1838 if (val) {
1839 set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1840 } else {
1841 clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
1842 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1843 }
1844
1845 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1846 if (err < 0)
1847 return err;
1848
Johan Hedberg562064e2014-07-08 16:35:34 +03001849 if (changed) {
Johan Hedberg432df052014-08-01 11:13:31 +03001850 hci_update_page_scan(hdev, NULL);
Johan Hedberg562064e2014-07-08 16:35:34 +03001851 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001852 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001853 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001854
1855 return 0;
1856}
1857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001858static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001859 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001860{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001861 struct mgmt_mode *cp = data;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001862 struct pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001863 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001864 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001865 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001866
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001867 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001868
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001869 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
1870 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedberg33c525c2012-10-24 21:11:58 +03001871 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001872 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001873
Johan Hedberga7e80f22013-01-09 16:05:19 +02001874 if (cp->val != 0x00 && cp->val != 0x01)
1875 return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1876 MGMT_STATUS_INVALID_PARAMS);
1877
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001879
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001880 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001881 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001882 goto failed;
1883 }
1884
1885 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001886 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001887 err = cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001888 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001889 goto failed;
1890 }
1891
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001892 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1893 if (!cmd) {
1894 err = -ENOMEM;
1895 goto failed;
1896 }
1897
Johan Hedberg2b76f452013-03-15 17:07:04 -05001898 hci_req_init(&req, hdev);
1899
Johan Hedberg9a43e252013-10-20 19:00:07 +03001900 /* If BR/EDR is not enabled and we disable advertising as a
1901 * by-product of disabling connectable, we need to update the
1902 * advertising flags.
1903 */
1904 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
1905 if (!cp->val) {
1906 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
1907 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
1908 }
1909 update_adv_data(&req);
1910 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001911 if (cp->val) {
1912 scan = SCAN_PAGE;
1913 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001914 /* If we don't have any whitelist entries just
1915 * disable all scanning. If there are entries
1916 * and we had both page and inquiry scanning
1917 * enabled then fall back to only page scanning.
1918 * Otherwise no changes are needed.
1919 */
1920 if (list_empty(&hdev->whitelist))
1921 scan = SCAN_DISABLED;
1922 else if (test_bit(HCI_ISCAN, &hdev->flags))
1923 scan = SCAN_PAGE;
1924 else
1925 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001926
1927 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001928 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001929 cancel_delayed_work(&hdev->discov_off);
1930 }
1931
1932 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1933 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001934
Johan Hedberg3bd27242014-07-28 20:53:58 +03001935no_scan_update:
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001936 /* If we're going from non-connectable to connectable or
1937 * vice-versa when fast connectable is enabled ensure that fast
1938 * connectable gets disabled. write_fast_connectable won't do
1939 * anything if the page scan parameters are already what they
1940 * should be.
1941 */
1942 if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags))
Johan Hedberge36a3762013-03-15 17:07:10 -05001943 write_fast_connectable(&req, false);
1944
Johan Hedberge8b12022014-07-10 10:51:27 +03001945 /* Update the advertising parameters if necessary */
1946 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001947 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001948
Johan Hedberg2b76f452013-03-15 17:07:04 -05001949 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03001950 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001951 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03001952 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03001953 err = set_connectable_update_settings(hdev, sk,
1954 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03001955 goto failed;
1956 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957
1958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001959 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001960 return err;
1961}
1962
Johan Hedbergb2939472014-07-30 09:22:23 +03001963static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001964 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02001965{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001966 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07001967 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02001968 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001969
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001970 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001971
Johan Hedberga7e80f22013-01-09 16:05:19 +02001972 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedbergb2939472014-07-30 09:22:23 +03001973 return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
Johan Hedberga7e80f22013-01-09 16:05:19 +02001974 MGMT_STATUS_INVALID_PARAMS);
1975
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001976 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001977
1978 if (cp->val)
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001979 changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001980 else
Johan Hedbergb6ae8452014-07-30 09:22:22 +03001981 changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001982
Johan Hedbergb2939472014-07-30 09:22:23 +03001983 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001984 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07001985 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001986
Marcel Holtmann55594352013-10-06 16:11:57 -07001987 if (changed)
1988 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001989
Marcel Holtmann55594352013-10-06 16:11:57 -07001990unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001991 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001992 return err;
1993}
Johan Hedberg72a734e2010-12-30 00:38:22 +02001994
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001995static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
1996 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02001997{
1998 struct mgmt_mode *cp = data;
1999 struct pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002000 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002001 int err;
2002
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002003 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002004
Johan Hedberge6fe7982013-10-02 15:45:22 +03002005 status = mgmt_bredr_support(hdev);
2006 if (status)
Johan Hedberg33c525c2012-10-24 21:11:58 +03002007 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Johan Hedberge6fe7982013-10-02 15:45:22 +03002008 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002009
Johan Hedberga7e80f22013-01-09 16:05:19 +02002010 if (cp->val != 0x00 && cp->val != 0x01)
2011 return cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2012 MGMT_STATUS_INVALID_PARAMS);
2013
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002014 hci_dev_lock(hdev);
2015
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002016 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002017 bool changed = false;
2018
2019 if (!!cp->val != test_bit(HCI_LINK_SECURITY,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002020 &hdev->dev_flags)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002021 change_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
2022 changed = true;
2023 }
2024
2025 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2026 if (err < 0)
2027 goto failed;
2028
2029 if (changed)
2030 err = new_settings(hdev, sk);
2031
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002032 goto failed;
2033 }
2034
2035 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002036 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002037 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002038 goto failed;
2039 }
2040
2041 val = !!cp->val;
2042
2043 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2044 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2045 goto failed;
2046 }
2047
2048 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2049 if (!cmd) {
2050 err = -ENOMEM;
2051 goto failed;
2052 }
2053
2054 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2055 if (err < 0) {
2056 mgmt_pending_remove(cmd);
2057 goto failed;
2058 }
2059
2060failed:
2061 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002062 return err;
2063}
2064
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002065static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002066{
2067 struct mgmt_mode *cp = data;
2068 struct pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002069 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002070 int err;
2071
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002072 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002073
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002074 status = mgmt_bredr_support(hdev);
2075 if (status)
2076 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
2077
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002078 if (!lmp_ssp_capable(hdev))
2079 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002081
Johan Hedberga7e80f22013-01-09 16:05:19 +02002082 if (cp->val != 0x00 && cp->val != 0x01)
2083 return cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2084 MGMT_STATUS_INVALID_PARAMS);
2085
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002086 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002087
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002088 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002089 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002090
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002091 if (cp->val) {
2092 changed = !test_and_set_bit(HCI_SSP_ENABLED,
2093 &hdev->dev_flags);
2094 } else {
2095 changed = test_and_clear_bit(HCI_SSP_ENABLED,
2096 &hdev->dev_flags);
2097 if (!changed)
2098 changed = test_and_clear_bit(HCI_HS_ENABLED,
2099 &hdev->dev_flags);
2100 else
2101 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002102 }
2103
2104 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2105 if (err < 0)
2106 goto failed;
2107
2108 if (changed)
2109 err = new_settings(hdev, sk);
2110
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002111 goto failed;
2112 }
2113
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002114 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) ||
2115 mgmt_pending_find(MGMT_OP_SET_HS, hdev)) {
Szymon Jancd97dcb62012-03-16 16:02:56 +01002116 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2117 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002118 goto failed;
2119 }
2120
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002121 if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002122 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2123 goto failed;
2124 }
2125
2126 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2127 if (!cmd) {
2128 err = -ENOMEM;
2129 goto failed;
2130 }
2131
Johan Hedberg37699722014-06-24 14:00:27 +03002132 if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
2133 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2134 sizeof(cp->val), &cp->val);
2135
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002136 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002137 if (err < 0) {
2138 mgmt_pending_remove(cmd);
2139 goto failed;
2140 }
2141
2142failed:
2143 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002144 return err;
2145}
2146
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002147static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002148{
2149 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002150 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002151 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002152 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002153
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002154 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002155
Johan Hedberge6fe7982013-10-02 15:45:22 +03002156 status = mgmt_bredr_support(hdev);
2157 if (status)
2158 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002159
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002160 if (!lmp_ssp_capable(hdev))
2161 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2162 MGMT_STATUS_NOT_SUPPORTED);
2163
2164 if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags))
2165 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2166 MGMT_STATUS_REJECTED);
2167
Johan Hedberga7e80f22013-01-09 16:05:19 +02002168 if (cp->val != 0x00 && cp->val != 0x01)
2169 return cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2170 MGMT_STATUS_INVALID_PARAMS);
2171
Marcel Holtmannee392692013-10-01 22:59:23 -07002172 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002173
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002174 if (cp->val) {
Marcel Holtmannee392692013-10-01 22:59:23 -07002175 changed = !test_and_set_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002176 } else {
2177 if (hdev_is_powered(hdev)) {
2178 err = cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2179 MGMT_STATUS_REJECTED);
2180 goto unlock;
2181 }
2182
Marcel Holtmannee392692013-10-01 22:59:23 -07002183 changed = test_and_clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002184 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002185
2186 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2187 if (err < 0)
2188 goto unlock;
2189
2190 if (changed)
2191 err = new_settings(hdev, sk);
2192
2193unlock:
2194 hci_dev_unlock(hdev);
2195 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002196}
2197
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002198static void le_enable_complete(struct hci_dev *hdev, u8 status)
2199{
2200 struct cmd_lookup match = { NULL, hdev };
2201
2202 if (status) {
2203 u8 mgmt_err = mgmt_status(status);
2204
2205 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2206 &mgmt_err);
2207 return;
2208 }
2209
2210 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2211
2212 new_settings(hdev, match.sk);
2213
2214 if (match.sk)
2215 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002216
2217 /* Make sure the controller has a good default for
2218 * advertising data. Restrict the update to when LE
2219 * has actually been enabled. During power on, the
2220 * update in powered_update_hci will take care of it.
2221 */
2222 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2223 struct hci_request req;
2224
2225 hci_dev_lock(hdev);
2226
2227 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002228 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002229 update_scan_rsp_data(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002230 hci_req_run(&req, NULL);
2231
Johan Hedberga70f4b52014-07-07 15:19:50 +03002232 hci_update_background_scan(hdev);
2233
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002234 hci_dev_unlock(hdev);
2235 }
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002236}
2237
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002238static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002239{
2240 struct mgmt_mode *cp = data;
2241 struct hci_cp_write_le_host_supported hci_cp;
2242 struct pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002243 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002244 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002245 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002246
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002247 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002248
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002249 if (!lmp_le_capable(hdev))
2250 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2251 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002252
Johan Hedberga7e80f22013-01-09 16:05:19 +02002253 if (cp->val != 0x00 && cp->val != 0x01)
2254 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2255 MGMT_STATUS_INVALID_PARAMS);
2256
Johan Hedbergc73eee92013-04-19 18:35:21 +03002257 /* LE-only devices do not allow toggling LE on/off */
Johan Hedberg56f87902013-10-02 13:43:13 +03002258 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
Johan Hedbergc73eee92013-04-19 18:35:21 +03002259 return cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2260 MGMT_STATUS_REJECTED);
2261
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002262 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002263
2264 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002265 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002266
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002267 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002268 bool changed = false;
2269
2270 if (val != test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
2271 change_bit(HCI_LE_ENABLED, &hdev->dev_flags);
2272 changed = true;
2273 }
2274
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02002275 if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
2276 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002277 changed = true;
2278 }
2279
Johan Hedberg06199cf2012-02-22 16:37:11 +02002280 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2281 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002282 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002283
2284 if (changed)
2285 err = new_settings(hdev, sk);
2286
Johan Hedberg1de028c2012-02-29 19:55:35 -08002287 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002288 }
2289
Johan Hedberg4375f102013-09-25 13:26:10 +03002290 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2291 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002292 err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002293 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002294 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002295 }
2296
2297 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2298 if (!cmd) {
2299 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002300 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002301 }
2302
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002303 hci_req_init(&req, hdev);
2304
Johan Hedberg06199cf2012-02-22 16:37:11 +02002305 memset(&hci_cp, 0, sizeof(hci_cp));
2306
2307 if (val) {
2308 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002309 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002310 } else {
Johan Hedberg73e082f2014-07-08 15:07:51 +03002311 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002312 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002313 }
2314
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002315 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2316 &hci_cp);
2317
2318 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302319 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002320 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
Johan Hedberg1de028c2012-02-29 19:55:35 -08002322unlock:
2323 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324 return err;
2325}
2326
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002327/* This is a helper function to test for pending mgmt commands that can
2328 * cause CoD or EIR HCI commands. We can only allow one such pending
2329 * mgmt command at a time since otherwise we cannot easily track what
2330 * the current values are, will be, and based on that calculate if a new
2331 * HCI command needs to be sent and if yes with what value.
2332 */
2333static bool pending_eir_or_class(struct hci_dev *hdev)
2334{
2335 struct pending_cmd *cmd;
2336
2337 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2338 switch (cmd->opcode) {
2339 case MGMT_OP_ADD_UUID:
2340 case MGMT_OP_REMOVE_UUID:
2341 case MGMT_OP_SET_DEV_CLASS:
2342 case MGMT_OP_SET_POWERED:
2343 return true;
2344 }
2345 }
2346
2347 return false;
2348}
2349
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002350static const u8 bluetooth_base_uuid[] = {
2351 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2352 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2353};
2354
2355static u8 get_uuid_size(const u8 *uuid)
2356{
2357 u32 val;
2358
2359 if (memcmp(uuid, bluetooth_base_uuid, 12))
2360 return 128;
2361
2362 val = get_unaligned_le32(&uuid[12]);
2363 if (val > 0xffff)
2364 return 32;
2365
2366 return 16;
2367}
2368
Johan Hedberg92da6092013-03-15 17:06:55 -05002369static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2370{
2371 struct pending_cmd *cmd;
2372
2373 hci_dev_lock(hdev);
2374
2375 cmd = mgmt_pending_find(mgmt_op, hdev);
2376 if (!cmd)
2377 goto unlock;
2378
2379 cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
2380 hdev->dev_class, 3);
2381
2382 mgmt_pending_remove(cmd);
2383
2384unlock:
2385 hci_dev_unlock(hdev);
2386}
2387
2388static void add_uuid_complete(struct hci_dev *hdev, u8 status)
2389{
2390 BT_DBG("status 0x%02x", status);
2391
2392 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2393}
2394
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002395static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002396{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002397 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002398 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002399 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002400 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002401 int err;
2402
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002403 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002404
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002405 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002406
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002407 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002408 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002409 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002410 goto failed;
2411 }
2412
Andre Guedes92c4c202012-06-07 19:05:44 -03002413 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002414 if (!uuid) {
2415 err = -ENOMEM;
2416 goto failed;
2417 }
2418
2419 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002420 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002421 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002422
Johan Hedbergde66aa62013-01-27 00:31:27 +02002423 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002424
Johan Hedberg890ea892013-03-15 17:06:52 -05002425 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002426
Johan Hedberg890ea892013-03-15 17:06:52 -05002427 update_class(&req);
2428 update_eir(&req);
2429
Johan Hedberg92da6092013-03-15 17:06:55 -05002430 err = hci_req_run(&req, add_uuid_complete);
2431 if (err < 0) {
2432 if (err != -ENODATA)
2433 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002435 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002436 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002437 goto failed;
2438 }
2439
2440 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002441 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002442 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002443 goto failed;
2444 }
2445
2446 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002447
2448failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002449 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002450 return err;
2451}
2452
Johan Hedberg24b78d02012-02-23 23:24:30 +02002453static bool enable_service_cache(struct hci_dev *hdev)
2454{
2455 if (!hdev_is_powered(hdev))
2456 return false;
2457
2458 if (!test_and_set_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002459 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2460 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002461 return true;
2462 }
2463
2464 return false;
2465}
2466
Johan Hedberg92da6092013-03-15 17:06:55 -05002467static void remove_uuid_complete(struct hci_dev *hdev, u8 status)
2468{
2469 BT_DBG("status 0x%02x", status);
2470
2471 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2472}
2473
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002474static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002475 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002476{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002477 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002478 struct pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002479 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480 u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Johan Hedberg890ea892013-03-15 17:06:52 -05002481 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482 int err, found;
2483
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002484 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002485
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002486 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002487
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002488 if (pending_eir_or_class(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002489 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002490 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002491 goto unlock;
2492 }
2493
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002494 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002495 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002496
Johan Hedberg24b78d02012-02-23 23:24:30 +02002497 if (enable_service_cache(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002498 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002499 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002500 goto unlock;
2501 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002502
Johan Hedberg9246a862012-02-23 21:33:16 +02002503 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002504 }
2505
2506 found = 0;
2507
Johan Hedberg056341c2013-01-27 00:31:30 +02002508 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002509 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2510 continue;
2511
2512 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002513 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002514 found++;
2515 }
2516
2517 if (found == 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002518 err = cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002519 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002520 goto unlock;
2521 }
2522
Johan Hedberg9246a862012-02-23 21:33:16 +02002523update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002524 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002525
Johan Hedberg890ea892013-03-15 17:06:52 -05002526 update_class(&req);
2527 update_eir(&req);
2528
Johan Hedberg92da6092013-03-15 17:06:55 -05002529 err = hci_req_run(&req, remove_uuid_complete);
2530 if (err < 0) {
2531 if (err != -ENODATA)
2532 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002535 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002536 goto unlock;
2537 }
2538
2539 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002540 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002541 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002542 goto unlock;
2543 }
2544
2545 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002546
2547unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002548 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002549 return err;
2550}
2551
Johan Hedberg92da6092013-03-15 17:06:55 -05002552static void set_class_complete(struct hci_dev *hdev, u8 status)
2553{
2554 BT_DBG("status 0x%02x", status);
2555
2556 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2557}
2558
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002559static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002560 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002561{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002562 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg90e70452012-02-23 23:09:40 +02002563 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002564 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002565 int err;
2566
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002567 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002568
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002569 if (!lmp_bredr_capable(hdev))
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002570 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2571 MGMT_STATUS_NOT_SUPPORTED);
2572
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002573 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002574
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002575 if (pending_eir_or_class(hdev)) {
2576 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2577 MGMT_STATUS_BUSY);
2578 goto unlock;
2579 }
2580
2581 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
2582 err = cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2583 MGMT_STATUS_INVALID_PARAMS);
2584 goto unlock;
2585 }
2586
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002587 hdev->major_class = cp->major;
2588 hdev->minor_class = cp->minor;
2589
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002590 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002591 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002592 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002593 goto unlock;
2594 }
2595
Johan Hedberg890ea892013-03-15 17:06:52 -05002596 hci_req_init(&req, hdev);
2597
Johan Hedberga8b2d5c2012-01-08 23:11:15 +02002598 if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002599 hci_dev_unlock(hdev);
2600 cancel_delayed_work_sync(&hdev->service_cache);
2601 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002602 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002603 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002604
Johan Hedberg890ea892013-03-15 17:06:52 -05002605 update_class(&req);
2606
Johan Hedberg92da6092013-03-15 17:06:55 -05002607 err = hci_req_run(&req, set_class_complete);
2608 if (err < 0) {
2609 if (err != -ENODATA)
2610 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002611
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002612 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002613 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002614 goto unlock;
2615 }
2616
2617 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002618 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002619 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002620 goto unlock;
2621 }
2622
2623 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624
Johan Hedbergb5235a62012-02-21 14:32:24 +02002625unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002626 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627 return err;
2628}
2629
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002630static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002631 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002632{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002633 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002634 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2635 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002636 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002637 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002638 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002639
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002640 BT_DBG("request for %s", hdev->name);
2641
2642 if (!lmp_bredr_capable(hdev))
2643 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2644 MGMT_STATUS_NOT_SUPPORTED);
2645
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002646 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002647 if (key_count > max_key_count) {
2648 BT_ERR("load_link_keys: too big key_count value %u",
2649 key_count);
2650 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2651 MGMT_STATUS_INVALID_PARAMS);
2652 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002653
Johan Hedberg86742e12011-11-07 23:13:38 +02002654 expected_len = sizeof(*cp) + key_count *
2655 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002656 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002657 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002658 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002659 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002660 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002661 }
2662
Johan Hedberg4ae143012013-01-20 14:27:13 +02002663 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
2664 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2665 MGMT_STATUS_INVALID_PARAMS);
2666
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002667 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002668 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002669
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002670 for (i = 0; i < key_count; i++) {
2671 struct mgmt_link_key_info *key = &cp->keys[i];
2672
Marcel Holtmann8e991132014-01-10 02:07:25 -08002673 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002674 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2675 MGMT_STATUS_INVALID_PARAMS);
2676 }
2677
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002678 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002679
2680 hci_link_keys_clear(hdev);
2681
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002682 if (cp->debug_keys)
Johan Hedberg0663b292014-06-24 13:15:50 +03002683 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
2684 &hdev->dev_flags);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002685 else
Johan Hedberg0663b292014-06-24 13:15:50 +03002686 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
2687 &hdev->dev_flags);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002688
2689 if (changed)
2690 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002692 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002693 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002694
Johan Hedberg58e92932014-06-24 14:00:26 +03002695 /* Always ignore debug keys and require a new pairing if
2696 * the user wants to use them.
2697 */
2698 if (key->type == HCI_LK_DEBUG_COMBINATION)
2699 continue;
2700
Johan Hedberg7652ff62014-06-24 13:15:49 +03002701 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2702 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002703 }
2704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002705 cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002708
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002709 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002710}
2711
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002712static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002713 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002714{
2715 struct mgmt_ev_device_unpaired ev;
2716
2717 bacpy(&ev.addr.bdaddr, bdaddr);
2718 ev.addr.type = addr_type;
2719
2720 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002721 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002722}
2723
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002724static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002725 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002726{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002727 struct mgmt_cp_unpair_device *cp = data;
2728 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002729 struct hci_cp_disconnect dc;
2730 struct pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002731 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002732 int err;
2733
Johan Hedberga8a1d192011-11-10 15:54:38 +02002734 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002735 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2736 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002737
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 if (!bdaddr_type_is_valid(cp->addr.type))
2739 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2740 MGMT_STATUS_INVALID_PARAMS,
2741 &rp, sizeof(rp));
2742
Johan Hedberg118da702013-01-20 14:27:20 +02002743 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
2744 return cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2745 MGMT_STATUS_INVALID_PARAMS,
2746 &rp, sizeof(rp));
2747
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002748 hci_dev_lock(hdev);
2749
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002750 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002751 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002752 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002753 goto unlock;
2754 }
2755
Johan Hedberge0b2b272014-02-18 17:14:31 +02002756 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002757 /* If disconnection is requested, then look up the
2758 * connection. If the remote device is connected, it
2759 * will be later used to terminate the link.
2760 *
2761 * Setting it to NULL explicitly will cause no
2762 * termination of the link.
2763 */
2764 if (cp->disconnect)
2765 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2766 &cp->addr.bdaddr);
2767 else
2768 conn = NULL;
2769
Johan Hedberg124f6e32012-02-09 13:50:12 +02002770 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002771 } else {
2772 u8 addr_type;
2773
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002774 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2775 &cp->addr.bdaddr);
2776 if (conn) {
2777 /* Defer clearing up the connection parameters
2778 * until closing to give a chance of keeping
2779 * them if a repairing happens.
2780 */
2781 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2782
2783 /* If disconnection is not requested, then
2784 * clear the connection variable so that the
2785 * link is not terminated.
2786 */
2787 if (!cp->disconnect)
2788 conn = NULL;
2789 }
2790
Johan Hedberge0b2b272014-02-18 17:14:31 +02002791 if (cp->addr.type == BDADDR_LE_PUBLIC)
2792 addr_type = ADDR_LE_DEV_PUBLIC;
2793 else
2794 addr_type = ADDR_LE_DEV_RANDOM;
2795
Johan Hedberga7ec7332014-02-18 17:14:35 +02002796 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2797
Johan Hedberge0b2b272014-02-18 17:14:31 +02002798 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2799 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002800
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002801 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002802 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002803 MGMT_STATUS_NOT_PAIRED, &rp, sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002804 goto unlock;
2805 }
2806
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002807 /* If the connection variable is set, then termination of the
2808 * link is requested.
2809 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002810 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002811 err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002812 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002813 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002814 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002815 }
2816
Johan Hedberg124f6e32012-02-09 13:50:12 +02002817 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002818 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002819 if (!cmd) {
2820 err = -ENOMEM;
2821 goto unlock;
2822 }
2823
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002824 cmd->cmd_complete = addr_cmd_complete;
2825
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002826 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002827 dc.reason = 0x13; /* Remote User Terminated Connection */
2828 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2829 if (err < 0)
2830 mgmt_pending_remove(cmd);
2831
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002832unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002833 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002834 return err;
2835}
2836
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002837static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002838 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002839{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002840 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002841 struct mgmt_rp_disconnect rp;
Johan Hedberg366a0332011-02-19 12:05:55 -03002842 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002843 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002844 int err;
2845
2846 BT_DBG("");
2847
Johan Hedberg06a63b12013-01-20 14:27:21 +02002848 memset(&rp, 0, sizeof(rp));
2849 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2850 rp.addr.type = cp->addr.type;
2851
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002852 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg06a63b12013-01-20 14:27:21 +02002853 return cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2854 MGMT_STATUS_INVALID_PARAMS,
2855 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002856
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002857 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002858
2859 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002860 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2861 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002862 goto failed;
2863 }
2864
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002865 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002866 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2867 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002868 goto failed;
2869 }
2870
Andre Guedes591f47f2012-04-24 21:02:49 -03002871 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002872 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2873 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002874 else
2875 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002876
Vishal Agarwalf9607272012-06-13 05:32:43 +05302877 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg06a63b12013-01-20 14:27:21 +02002878 err = cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2879 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002880 goto failed;
2881 }
2882
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002883 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002884 if (!cmd) {
2885 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002886 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002887 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002888
Johan Hedbergf5818c22014-12-05 13:36:02 +02002889 cmd->cmd_complete = generic_cmd_complete;
2890
Johan Hedberge3f2f922014-08-18 20:33:33 +03002891 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002892 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002893 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002894
2895failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002897 return err;
2898}
2899
Andre Guedes57c14772012-04-24 21:02:50 -03002900static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002901{
2902 switch (link_type) {
2903 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002904 switch (addr_type) {
2905 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002906 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002907
Johan Hedberg48264f02011-11-09 13:58:58 +02002908 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002909 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002910 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002911 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002912
Johan Hedberg4c659c32011-11-07 23:13:39 +02002913 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002914 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002915 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002916 }
2917}
2918
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002919static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2920 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002921{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002922 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002923 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002924 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002925 int err;
2926 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002927
2928 BT_DBG("");
2929
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002930 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002931
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002932 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002933 err = cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002934 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002935 goto unlock;
2936 }
2937
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002938 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02002939 list_for_each_entry(c, &hdev->conn_hash.list, list) {
2940 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002941 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002942 }
2943
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002944 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03002945 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02002946 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02002947 err = -ENOMEM;
2948 goto unlock;
2949 }
2950
Johan Hedberg2784eb42011-01-21 13:56:35 +02002951 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002952 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02002953 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
2954 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002955 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03002956 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03002957 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002958 continue;
2959 i++;
2960 }
2961
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002962 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002963
Johan Hedberg4c659c32011-11-07 23:13:39 +02002964 /* Recalculate length in case of filtered SCO connections, etc */
2965 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02002966
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002967 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002968 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002969
Johan Hedberga38528f2011-01-22 06:46:43 +02002970 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002971
2972unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002973 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002974 return err;
2975}
2976
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002977static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002978 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002979{
2980 struct pending_cmd *cmd;
2981 int err;
2982
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002983 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002985 if (!cmd)
2986 return -ENOMEM;
2987
Johan Hedbergd8457692012-02-17 14:24:57 +02002988 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002989 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002990 if (err < 0)
2991 mgmt_pending_remove(cmd);
2992
2993 return err;
2994}
2995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002996static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002997 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02002998{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02002999 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003000 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003001 struct hci_cp_pin_code_reply reply;
Johan Hedberg366a0332011-02-19 12:05:55 -03003002 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003003 int err;
3004
3005 BT_DBG("");
3006
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003007 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003008
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003009 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003010 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003011 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003012 goto failed;
3013 }
3014
Johan Hedbergd8457692012-02-17 14:24:57 +02003015 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003016 if (!conn) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003017 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003018 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003019 goto failed;
3020 }
3021
3022 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003023 struct mgmt_cp_pin_code_neg_reply ncp;
3024
3025 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003026
3027 BT_ERR("PIN code is not 16 bytes long");
3028
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003029 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003030 if (err >= 0)
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003031 err = cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003032 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003033
3034 goto failed;
3035 }
3036
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003037 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003038 if (!cmd) {
3039 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003040 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003041 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003042
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003043 cmd->cmd_complete = addr_cmd_complete;
3044
Johan Hedbergd8457692012-02-17 14:24:57 +02003045 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003046 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003047 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003048
3049 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3050 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003051 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003052
3053failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003054 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003055 return err;
3056}
3057
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003058static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3059 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003060{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003061 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003062
3063 BT_DBG("");
3064
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003065 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
3066 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3067 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
3068
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003069 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003070
3071 hdev->io_capability = cp->io_capability;
3072
3073 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003074 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003075
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003076 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003077
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003078 return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0, NULL,
3079 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003080}
3081
Gustavo Padovan6039aa72012-05-23 04:04:18 -03003082static struct pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003083{
3084 struct hci_dev *hdev = conn->hdev;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003085 struct pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003086
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003087 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003088 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3089 continue;
3090
Johan Hedberge9a416b2011-02-19 12:05:56 -03003091 if (cmd->user_data != conn)
3092 continue;
3093
3094 return cmd;
3095 }
3096
3097 return NULL;
3098}
3099
3100static void pairing_complete(struct pending_cmd *cmd, u8 status)
3101{
3102 struct mgmt_rp_pair_device rp;
3103 struct hci_conn *conn = cmd->user_data;
3104
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003105 bacpy(&rp.addr.bdaddr, &conn->dst);
3106 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003107
Johan Hedbergaee9b212012-02-18 15:07:59 +02003108 cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003109 &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003110
3111 /* So we don't get further callbacks for this connection */
3112 conn->connect_cfm_cb = NULL;
3113 conn->security_cfm_cb = NULL;
3114 conn->disconn_cfm_cb = NULL;
3115
David Herrmann76a68ba2013-04-06 20:28:37 +02003116 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003117 hci_conn_put(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003118
Johan Hedberga664b5b2011-02-19 12:06:02 -03003119 mgmt_pending_remove(cmd);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003120
3121 /* The device is paired so there is no need to remove
3122 * its connection parameters anymore.
3123 */
3124 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003125}
3126
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003127void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3128{
3129 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
3130 struct pending_cmd *cmd;
3131
3132 cmd = find_pairing(conn);
3133 if (cmd)
Johan Hedberg04ab2742014-12-05 13:36:04 +02003134 cmd->cmd_complete(cmd, status);
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003135}
3136
Johan Hedberge9a416b2011-02-19 12:05:56 -03003137static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3138{
3139 struct pending_cmd *cmd;
3140
3141 BT_DBG("status %u", status);
3142
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003143 cmd = find_pairing(conn);
3144 if (!cmd)
3145 BT_DBG("Unable to find a pending command");
3146 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003147 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148}
3149
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003150static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303151{
3152 struct pending_cmd *cmd;
3153
3154 BT_DBG("status %u", status);
3155
3156 if (!status)
3157 return;
3158
3159 cmd = find_pairing(conn);
3160 if (!cmd)
3161 BT_DBG("Unable to find a pending command");
3162 else
Johan Hedberg04ab2742014-12-05 13:36:04 +02003163 cmd->cmd_complete(cmd, mgmt_status(status));
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303164}
3165
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003166static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003167 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003168{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003169 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003170 struct mgmt_rp_pair_device rp;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003171 struct pending_cmd *cmd;
3172 u8 sec_level, auth_type;
3173 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003174 int err;
3175
3176 BT_DBG("");
3177
Szymon Jancf950a30e2013-01-18 12:48:07 +01003178 memset(&rp, 0, sizeof(rp));
3179 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3180 rp.addr.type = cp->addr.type;
3181
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003182 if (!bdaddr_type_is_valid(cp->addr.type))
3183 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3184 MGMT_STATUS_INVALID_PARAMS,
3185 &rp, sizeof(rp));
3186
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003187 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
3188 return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3189 MGMT_STATUS_INVALID_PARAMS,
3190 &rp, sizeof(rp));
3191
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003192 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003193
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003194 if (!hdev_is_powered(hdev)) {
Szymon Jancf950a30e2013-01-18 12:48:07 +01003195 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3196 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003197 goto unlock;
3198 }
3199
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003200 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003201 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003202
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003203 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003204 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3205 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003206 } else {
3207 u8 addr_type;
3208
3209 /* Convert from L2CAP channel address type to HCI address type
3210 */
3211 if (cp->addr.type == BDADDR_LE_PUBLIC)
3212 addr_type = ADDR_LE_DEV_PUBLIC;
3213 else
3214 addr_type = ADDR_LE_DEV_RANDOM;
3215
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003216 /* When pairing a new device, it is expected to remember
3217 * this device for future connections. Adding the connection
3218 * parameter information ahead of time allows tracking
3219 * of the slave preferred values and will speed up any
3220 * further connection establishment.
3221 *
3222 * If connection parameters already exist, then they
3223 * will be kept and this function does nothing.
3224 */
3225 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3226
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003227 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003228 sec_level, HCI_LE_CONN_TIMEOUT,
3229 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003230 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003231
Ville Tervo30e76272011-02-22 16:10:53 -03003232 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003233 int status;
3234
3235 if (PTR_ERR(conn) == -EBUSY)
3236 status = MGMT_STATUS_BUSY;
3237 else
3238 status = MGMT_STATUS_CONNECT_FAILED;
3239
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003240 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003241 status, &rp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003242 sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243 goto unlock;
3244 }
3245
3246 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003247 hci_conn_drop(conn);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003248 err = cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003249 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003250 goto unlock;
3251 }
3252
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003253 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003254 if (!cmd) {
3255 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003256 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003257 goto unlock;
3258 }
3259
Johan Hedberg04ab2742014-12-05 13:36:04 +02003260 cmd->cmd_complete = pairing_complete;
3261
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003262 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003263 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003264 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003265 conn->security_cfm_cb = pairing_complete_cb;
3266 conn->disconn_cfm_cb = pairing_complete_cb;
3267 } else {
3268 conn->connect_cfm_cb = le_pairing_complete_cb;
3269 conn->security_cfm_cb = le_pairing_complete_cb;
3270 conn->disconn_cfm_cb = le_pairing_complete_cb;
3271 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003272
Johan Hedberge9a416b2011-02-19 12:05:56 -03003273 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003274 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003275
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003276 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberge7cafc42014-07-17 15:35:38 +03003277 hci_conn_security(conn, sec_level, auth_type, true))
Johan Hedberge9a416b2011-02-19 12:05:56 -03003278 pairing_complete(cmd, 0);
3279
3280 err = 0;
3281
3282unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003283 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003284 return err;
3285}
3286
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003287static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3288 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003289{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003290 struct mgmt_addr_info *addr = data;
Johan Hedberg28424702012-02-02 04:02:29 +02003291 struct pending_cmd *cmd;
3292 struct hci_conn *conn;
3293 int err;
3294
3295 BT_DBG("");
3296
Johan Hedberg28424702012-02-02 04:02:29 +02003297 hci_dev_lock(hdev);
3298
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003299 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003300 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003301 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003302 goto unlock;
3303 }
3304
Johan Hedberg28424702012-02-02 04:02:29 +02003305 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3306 if (!cmd) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003307 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003308 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003309 goto unlock;
3310 }
3311
3312 conn = cmd->user_data;
3313
3314 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003315 err = cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003316 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003317 goto unlock;
3318 }
3319
3320 pairing_complete(cmd, MGMT_STATUS_CANCELLED);
3321
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003322 err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003323 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003324unlock:
3325 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003326 return err;
3327}
3328
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003329static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003330 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003331 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003332{
Johan Hedberga5c29682011-02-19 12:05:57 -03003333 struct pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003334 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003335 int err;
3336
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003337 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003338
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003339 if (!hdev_is_powered(hdev)) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003340 err = cmd_complete(sk, hdev->id, mgmt_op,
3341 MGMT_STATUS_NOT_POWERED, addr,
3342 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003343 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003344 }
3345
Johan Hedberg1707c602013-03-15 17:07:15 -05003346 if (addr->type == BDADDR_BREDR)
3347 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003348 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003349 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003350
Johan Hedberg272d90d2012-02-09 15:26:12 +02003351 if (!conn) {
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003352 err = cmd_complete(sk, hdev->id, mgmt_op,
3353 MGMT_STATUS_NOT_CONNECTED, addr,
3354 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003355 goto done;
3356 }
3357
Johan Hedberg1707c602013-03-15 17:07:15 -05003358 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003359 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003360 if (!err)
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003361 err = cmd_complete(sk, hdev->id, mgmt_op,
3362 MGMT_STATUS_SUCCESS, addr,
3363 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003364 else
Johan Hedbergfeb94d32013-03-15 17:07:16 -05003365 err = cmd_complete(sk, hdev->id, mgmt_op,
3366 MGMT_STATUS_FAILED, addr,
3367 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003368
Brian Gix47c15e22011-11-16 13:53:14 -08003369 goto done;
3370 }
3371
Johan Hedberg1707c602013-03-15 17:07:15 -05003372 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003373 if (!cmd) {
3374 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003375 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003376 }
3377
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003378 cmd->cmd_complete = addr_cmd_complete;
3379
Brian Gix0df4c182011-11-16 13:53:13 -08003380 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003381 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3382 struct hci_cp_user_passkey_reply cp;
3383
Johan Hedberg1707c602013-03-15 17:07:15 -05003384 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003385 cp.passkey = passkey;
3386 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3387 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003388 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3389 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003390
Johan Hedberga664b5b2011-02-19 12:06:02 -03003391 if (err < 0)
3392 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003393
Brian Gix0df4c182011-11-16 13:53:13 -08003394done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003395 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003396 return err;
3397}
3398
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303399static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3400 void *data, u16 len)
3401{
3402 struct mgmt_cp_pin_code_neg_reply *cp = data;
3403
3404 BT_DBG("");
3405
Johan Hedberg1707c602013-03-15 17:07:15 -05003406 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303407 MGMT_OP_PIN_CODE_NEG_REPLY,
3408 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3409}
3410
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003411static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3412 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003413{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003414 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003415
3416 BT_DBG("");
3417
3418 if (len != sizeof(*cp))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003419 return cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003421
Johan Hedberg1707c602013-03-15 17:07:15 -05003422 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003423 MGMT_OP_USER_CONFIRM_REPLY,
3424 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003425}
3426
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003427static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003428 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003429{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003430 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003431
3432 BT_DBG("");
3433
Johan Hedberg1707c602013-03-15 17:07:15 -05003434 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003435 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3436 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003437}
3438
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003439static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3440 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003441{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003442 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003443
3444 BT_DBG("");
3445
Johan Hedberg1707c602013-03-15 17:07:15 -05003446 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003447 MGMT_OP_USER_PASSKEY_REPLY,
3448 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003449}
3450
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003451static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003452 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003453{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003454 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003455
3456 BT_DBG("");
3457
Johan Hedberg1707c602013-03-15 17:07:15 -05003458 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003459 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3460 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003461}
3462
Johan Hedberg13928972013-03-15 17:07:00 -05003463static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003464{
Johan Hedberg13928972013-03-15 17:07:00 -05003465 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003466 struct hci_cp_write_local_name cp;
3467
Johan Hedberg13928972013-03-15 17:07:00 -05003468 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003469
Johan Hedberg890ea892013-03-15 17:06:52 -05003470 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003471}
3472
Johan Hedberg13928972013-03-15 17:07:00 -05003473static void set_name_complete(struct hci_dev *hdev, u8 status)
3474{
3475 struct mgmt_cp_set_local_name *cp;
3476 struct pending_cmd *cmd;
3477
3478 BT_DBG("status 0x%02x", status);
3479
3480 hci_dev_lock(hdev);
3481
3482 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3483 if (!cmd)
3484 goto unlock;
3485
3486 cp = cmd->param;
3487
3488 if (status)
3489 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3490 mgmt_status(status));
3491 else
3492 cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3493 cp, sizeof(*cp));
3494
3495 mgmt_pending_remove(cmd);
3496
3497unlock:
3498 hci_dev_unlock(hdev);
3499}
3500
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003501static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003502 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003503{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003504 struct mgmt_cp_set_local_name *cp = data;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003505 struct pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003506 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003507 int err;
3508
3509 BT_DBG("");
3510
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003511 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003512
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003513 /* If the old values are the same as the new ones just return a
3514 * direct command complete event.
3515 */
3516 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3517 !memcmp(hdev->short_name, cp->short_name,
3518 sizeof(hdev->short_name))) {
3519 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3520 data, len);
3521 goto failed;
3522 }
3523
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003524 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003525
Johan Hedbergb5235a62012-02-21 14:32:24 +02003526 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003527 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003528
3529 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003530 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003531 if (err < 0)
3532 goto failed;
3533
3534 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003535 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003536
Johan Hedbergb5235a62012-02-21 14:32:24 +02003537 goto failed;
3538 }
3539
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003540 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003541 if (!cmd) {
3542 err = -ENOMEM;
3543 goto failed;
3544 }
3545
Johan Hedberg13928972013-03-15 17:07:00 -05003546 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3547
Johan Hedberg890ea892013-03-15 17:06:52 -05003548 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003549
3550 if (lmp_bredr_capable(hdev)) {
3551 update_name(&req);
3552 update_eir(&req);
3553 }
3554
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003555 /* The name is stored in the scan response data and so
3556 * no need to udpate the advertising data here.
3557 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003558 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003559 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003560
Johan Hedberg13928972013-03-15 17:07:00 -05003561 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003562 if (err < 0)
3563 mgmt_pending_remove(cmd);
3564
3565failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003566 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003567 return err;
3568}
3569
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003570static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003571 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003572{
Szymon Jancc35938b2011-03-22 13:12:21 +01003573 struct pending_cmd *cmd;
3574 int err;
3575
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003576 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003577
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003578 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003579
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003580 if (!hdev_is_powered(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003581 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003582 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003583 goto unlock;
3584 }
3585
Andre Guedes9a1a1992012-07-24 15:03:48 -03003586 if (!lmp_ssp_capable(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003587 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003588 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003589 goto unlock;
3590 }
3591
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003592 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003593 err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003594 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003595 goto unlock;
3596 }
3597
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003598 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003599 if (!cmd) {
3600 err = -ENOMEM;
3601 goto unlock;
3602 }
3603
Johan Hedberg710f11c2014-05-26 11:21:22 +03003604 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003605 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3606 0, NULL);
3607 else
3608 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3609
Szymon Jancc35938b2011-03-22 13:12:21 +01003610 if (err < 0)
3611 mgmt_pending_remove(cmd);
3612
3613unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003614 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003615 return err;
3616}
3617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003618static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003619 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003620{
Szymon Janc2763eda2011-03-22 13:12:22 +01003621 int err;
3622
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003623 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003624
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003625 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003626
Marcel Holtmannec109112014-01-10 02:07:30 -08003627 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3628 struct mgmt_cp_add_remote_oob_data *cp = data;
3629 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003630
Johan Hedbergc19a4952014-11-17 20:52:19 +02003631 if (cp->addr.type != BDADDR_BREDR) {
3632 err = cmd_complete(sk, hdev->id,
3633 MGMT_OP_ADD_REMOTE_OOB_DATA,
3634 MGMT_STATUS_INVALID_PARAMS,
3635 &cp->addr, sizeof(cp->addr));
3636 goto unlock;
3637 }
3638
Marcel Holtmannec109112014-01-10 02:07:30 -08003639 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003640 cp->addr.type, cp->hash,
3641 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003642 if (err < 0)
3643 status = MGMT_STATUS_FAILED;
3644 else
3645 status = MGMT_STATUS_SUCCESS;
3646
3647 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3648 status, &cp->addr, sizeof(cp->addr));
3649 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3650 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Johan Hedberg86df9202014-10-26 20:52:27 +01003651 u8 *rand192, *hash192;
Marcel Holtmannec109112014-01-10 02:07:30 -08003652 u8 status;
3653
Johan Hedbergc19a4952014-11-17 20:52:19 +02003654 if (cp->addr.type != BDADDR_BREDR) {
3655 err = cmd_complete(sk, hdev->id,
3656 MGMT_OP_ADD_REMOTE_OOB_DATA,
3657 MGMT_STATUS_INVALID_PARAMS,
3658 &cp->addr, sizeof(cp->addr));
3659 goto unlock;
3660 }
3661
Johan Hedberg86df9202014-10-26 20:52:27 +01003662 if (bdaddr_type_is_le(cp->addr.type)) {
3663 rand192 = NULL;
3664 hash192 = NULL;
3665 } else {
3666 rand192 = cp->rand192;
3667 hash192 = cp->hash192;
3668 }
3669
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003670 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003671 cp->addr.type, hash192, rand192,
3672 cp->hash256, cp->rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003673 if (err < 0)
3674 status = MGMT_STATUS_FAILED;
3675 else
3676 status = MGMT_STATUS_SUCCESS;
3677
3678 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3679 status, &cp->addr, sizeof(cp->addr));
3680 } else {
3681 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
3682 err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3683 MGMT_STATUS_INVALID_PARAMS);
3684 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003685
Johan Hedbergc19a4952014-11-17 20:52:19 +02003686unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003687 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003688 return err;
3689}
3690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003691static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003692 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003693{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003694 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003695 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003696 int err;
3697
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003698 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003699
Johan Hedbergc19a4952014-11-17 20:52:19 +02003700 if (cp->addr.type != BDADDR_BREDR)
3701 return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3702 MGMT_STATUS_INVALID_PARAMS,
3703 &cp->addr, sizeof(cp->addr));
3704
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003705 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003706
Johan Hedbergeedbd582014-11-15 09:34:23 +02003707 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3708 hci_remote_oob_data_clear(hdev);
3709 status = MGMT_STATUS_SUCCESS;
3710 goto done;
3711 }
3712
Johan Hedberg6928a922014-10-26 20:46:09 +01003713 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003714 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003715 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003716 else
Szymon Janca6785be2012-12-13 15:11:21 +01003717 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003718
Johan Hedbergeedbd582014-11-15 09:34:23 +02003719done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003720 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003721 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003722
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003723 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003724 return err;
3725}
3726
Marcel Holtmann80190442014-12-04 11:36:36 +01003727static bool trigger_discovery(struct hci_request *req, u8 *status)
3728{
3729 struct hci_dev *hdev = req->hdev;
3730 struct hci_cp_le_set_scan_param param_cp;
3731 struct hci_cp_le_set_scan_enable enable_cp;
3732 struct hci_cp_inquiry inq_cp;
3733 /* General inquiry access code (GIAC) */
3734 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3735 u8 own_addr_type;
3736 int err;
3737
3738 switch (hdev->discovery.type) {
3739 case DISCOV_TYPE_BREDR:
3740 *status = mgmt_bredr_support(hdev);
3741 if (*status)
3742 return false;
3743
3744 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3745 *status = MGMT_STATUS_BUSY;
3746 return false;
3747 }
3748
3749 hci_inquiry_cache_flush(hdev);
3750
3751 memset(&inq_cp, 0, sizeof(inq_cp));
3752 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3753 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3754 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3755 break;
3756
3757 case DISCOV_TYPE_LE:
3758 case DISCOV_TYPE_INTERLEAVED:
3759 *status = mgmt_le_support(hdev);
3760 if (*status)
3761 return false;
3762
3763 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
3764 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
3765 *status = MGMT_STATUS_NOT_SUPPORTED;
3766 return false;
3767 }
3768
3769 if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
3770 /* Don't let discovery abort an outgoing
3771 * connection attempt that's using directed
3772 * advertising.
3773 */
3774 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3775 BT_CONNECT)) {
3776 *status = MGMT_STATUS_REJECTED;
3777 return false;
3778 }
3779
3780 disable_advertising(req);
3781 }
3782
3783 /* If controller is scanning, it means the background scanning
3784 * is running. Thus, we should temporarily stop it in order to
3785 * set the discovery scanning parameters.
3786 */
3787 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
3788 hci_req_add_le_scan_disable(req);
3789
3790 memset(&param_cp, 0, sizeof(param_cp));
3791
3792 /* All active scans will be done with either a resolvable
3793 * private address (when privacy feature has been enabled)
3794 * or unresolvable private address.
3795 */
3796 err = hci_update_random_address(req, true, &own_addr_type);
3797 if (err < 0) {
3798 *status = MGMT_STATUS_FAILED;
3799 return false;
3800 }
3801
3802 param_cp.type = LE_SCAN_ACTIVE;
3803 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3804 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3805 param_cp.own_address_type = own_addr_type;
3806 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3807 &param_cp);
3808
3809 memset(&enable_cp, 0, sizeof(enable_cp));
3810 enable_cp.enable = LE_SCAN_ENABLE;
3811 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3812 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3813 &enable_cp);
3814 break;
3815
3816 default:
3817 *status = MGMT_STATUS_INVALID_PARAMS;
3818 return false;
3819 }
3820
3821 return true;
3822}
3823
Andre Guedes7c307722013-04-30 15:29:28 -03003824static void start_discovery_complete(struct hci_dev *hdev, u8 status)
3825{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003826 struct pending_cmd *cmd;
3827 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003828
Andre Guedes7c307722013-04-30 15:29:28 -03003829 BT_DBG("status %d", status);
3830
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003831 hci_dev_lock(hdev);
3832
3833 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003834 if (!cmd)
3835 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3836
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003837 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003838 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003839 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003840 }
3841
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003842 if (status) {
3843 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3844 goto unlock;
3845 }
3846
Andre Guedes7c307722013-04-30 15:29:28 -03003847 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003848
3849 switch (hdev->discovery.type) {
3850 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003851 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003852 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003853 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003854 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003855 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003856 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003857 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003858 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003859 default:
3860 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003861 timeout = 0;
3862 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003863 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003864
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003865 if (timeout)
3866 queue_delayed_work(hdev->workqueue,
3867 &hdev->le_scan_disable, timeout);
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003868
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003869unlock:
3870 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03003871}
3872
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003873static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003874 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04003875{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003876 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04003877 struct pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03003878 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01003879 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04003880 int err;
3881
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003882 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04003883
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003884 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003885
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003886 if (!hdev_is_powered(hdev)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003887 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3888 MGMT_STATUS_NOT_POWERED,
3889 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02003890 goto failed;
3891 }
3892
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003893 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3894 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003895 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
3896 MGMT_STATUS_BUSY, &cp->type,
3897 sizeof(cp->type));
Johan Hedbergff9ef572012-01-04 14:23:45 +02003898 goto failed;
3899 }
3900
Johan Hedberg2922a942014-12-05 13:36:06 +02003901 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04003902 if (!cmd) {
3903 err = -ENOMEM;
3904 goto failed;
3905 }
3906
Johan Hedberg2922a942014-12-05 13:36:06 +02003907 cmd->cmd_complete = generic_cmd_complete;
3908
Marcel Holtmann22078802014-12-05 11:45:22 +01003909 /* Clear the discovery filter first to free any previously
3910 * allocated memory for the UUID list.
3911 */
3912 hci_discovery_filter_clear(hdev);
3913
Andre Guedes4aab14e2012-02-17 20:39:36 -03003914 hdev->discovery.type = cp->type;
3915
Andre Guedes7c307722013-04-30 15:29:28 -03003916 hci_req_init(&req, hdev);
3917
Marcel Holtmann80190442014-12-04 11:36:36 +01003918 if (!trigger_discovery(&req, &status)) {
Szymon Janca736abc2014-11-03 14:20:56 +01003919 err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
Marcel Holtmann80190442014-12-04 11:36:36 +01003920 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02003921 mgmt_pending_remove(cmd);
3922 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03003923 }
Andre Guedes3fd24152012-02-03 17:48:01 -03003924
Andre Guedes7c307722013-04-30 15:29:28 -03003925 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003926 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04003927 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01003928 goto failed;
3929 }
3930
3931 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04003932
3933failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003934 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04003935 return err;
3936}
3937
Johan Hedberg2922a942014-12-05 13:36:06 +02003938static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
3939{
3940 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
3941}
3942
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003943static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
3944 void *data, u16 len)
3945{
3946 struct mgmt_cp_start_service_discovery *cp = data;
3947 struct pending_cmd *cmd;
3948 struct hci_request req;
3949 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
3950 u16 uuid_count, expected_len;
3951 u8 status;
3952 int err;
3953
3954 BT_DBG("%s", hdev->name);
3955
3956 hci_dev_lock(hdev);
3957
3958 if (!hdev_is_powered(hdev)) {
3959 err = cmd_complete(sk, hdev->id,
3960 MGMT_OP_START_SERVICE_DISCOVERY,
3961 MGMT_STATUS_NOT_POWERED,
3962 &cp->type, sizeof(cp->type));
3963 goto failed;
3964 }
3965
3966 if (hdev->discovery.state != DISCOVERY_STOPPED ||
3967 test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
3968 err = cmd_complete(sk, hdev->id,
3969 MGMT_OP_START_SERVICE_DISCOVERY,
3970 MGMT_STATUS_BUSY, &cp->type,
3971 sizeof(cp->type));
3972 goto failed;
3973 }
3974
3975 uuid_count = __le16_to_cpu(cp->uuid_count);
3976 if (uuid_count > max_uuid_count) {
3977 BT_ERR("service_discovery: too big uuid_count value %u",
3978 uuid_count);
3979 err = cmd_complete(sk, hdev->id,
3980 MGMT_OP_START_SERVICE_DISCOVERY,
3981 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3982 sizeof(cp->type));
3983 goto failed;
3984 }
3985
3986 expected_len = sizeof(*cp) + uuid_count * 16;
3987 if (expected_len != len) {
3988 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
3989 expected_len, len);
3990 err = cmd_complete(sk, hdev->id,
3991 MGMT_OP_START_SERVICE_DISCOVERY,
3992 MGMT_STATUS_INVALID_PARAMS, &cp->type,
3993 sizeof(cp->type));
3994 goto failed;
3995 }
3996
3997 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02003998 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003999 if (!cmd) {
4000 err = -ENOMEM;
4001 goto failed;
4002 }
4003
Johan Hedberg2922a942014-12-05 13:36:06 +02004004 cmd->cmd_complete = service_discovery_cmd_complete;
4005
Marcel Holtmann22078802014-12-05 11:45:22 +01004006 /* Clear the discovery filter first to free any previously
4007 * allocated memory for the UUID list.
4008 */
4009 hci_discovery_filter_clear(hdev);
4010
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004011 hdev->discovery.type = cp->type;
4012 hdev->discovery.rssi = cp->rssi;
4013 hdev->discovery.uuid_count = uuid_count;
4014
4015 if (uuid_count > 0) {
4016 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4017 GFP_KERNEL);
4018 if (!hdev->discovery.uuids) {
4019 err = cmd_complete(sk, hdev->id,
4020 MGMT_OP_START_SERVICE_DISCOVERY,
4021 MGMT_STATUS_FAILED,
4022 &cp->type, sizeof(cp->type));
4023 mgmt_pending_remove(cmd);
4024 goto failed;
4025 }
4026 }
4027
4028 hci_req_init(&req, hdev);
4029
4030 if (!trigger_discovery(&req, &status)) {
4031 err = cmd_complete(sk, hdev->id,
4032 MGMT_OP_START_SERVICE_DISCOVERY,
4033 status, &cp->type, sizeof(cp->type));
4034 mgmt_pending_remove(cmd);
4035 goto failed;
4036 }
4037
4038 err = hci_req_run(&req, start_discovery_complete);
4039 if (err < 0) {
4040 mgmt_pending_remove(cmd);
4041 goto failed;
4042 }
4043
4044 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4045
4046failed:
4047 hci_dev_unlock(hdev);
4048 return err;
4049}
4050
Andre Guedes0e05bba2013-04-30 15:29:33 -03004051static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
4052{
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004053 struct pending_cmd *cmd;
4054
Andre Guedes0e05bba2013-04-30 15:29:33 -03004055 BT_DBG("status %d", status);
4056
4057 hci_dev_lock(hdev);
4058
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004059 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4060 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004061 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004062 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004063 }
4064
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004065 if (!status)
4066 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004067
Andre Guedes0e05bba2013-04-30 15:29:33 -03004068 hci_dev_unlock(hdev);
4069}
4070
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004071static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004072 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004073{
Johan Hedbergd9306502012-02-20 23:25:18 +02004074 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg14a53662011-04-27 10:29:56 -04004075 struct pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004076 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004077 int err;
4078
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004079 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004080
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004081 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004082
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004083 if (!hci_discovery_active(hdev)) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004084 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004085 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4086 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004087 goto unlock;
4088 }
4089
4090 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004091 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004092 MGMT_STATUS_INVALID_PARAMS, &mgmt_cp->type,
4093 sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004094 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004095 }
4096
Johan Hedberg2922a942014-12-05 13:36:06 +02004097 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004098 if (!cmd) {
4099 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004100 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004101 }
4102
Johan Hedberg2922a942014-12-05 13:36:06 +02004103 cmd->cmd_complete = generic_cmd_complete;
4104
Andre Guedes0e05bba2013-04-30 15:29:33 -03004105 hci_req_init(&req, hdev);
4106
Johan Hedberg21a60d32014-06-10 14:05:58 +03004107 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004108
Johan Hedberg21a60d32014-06-10 14:05:58 +03004109 err = hci_req_run(&req, stop_discovery_complete);
4110 if (!err) {
4111 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004112 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004113 }
4114
Johan Hedberg21a60d32014-06-10 14:05:58 +03004115 mgmt_pending_remove(cmd);
4116
4117 /* If no HCI commands were sent we're done */
4118 if (err == -ENODATA) {
4119 err = cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4120 &mgmt_cp->type, sizeof(mgmt_cp->type));
4121 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4122 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004123
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004124unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004125 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004126 return err;
4127}
4128
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004129static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004130 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004131{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004132 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004133 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004134 int err;
4135
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004136 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004137
Johan Hedberg561aafb2012-01-04 13:31:59 +02004138 hci_dev_lock(hdev);
4139
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004140 if (!hci_discovery_active(hdev)) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004141 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4142 MGMT_STATUS_FAILED, &cp->addr,
4143 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004144 goto failed;
4145 }
4146
Johan Hedberga198e7b2012-02-17 14:27:06 +02004147 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004148 if (!e) {
Lukasz Rymanowskid3a25412014-02-27 16:47:28 +01004149 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4150 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4151 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004152 goto failed;
4153 }
4154
4155 if (cp->name_known) {
4156 e->name_state = NAME_KNOWN;
4157 list_del(&e->list);
4158 } else {
4159 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e20a2012-01-09 00:53:02 +02004160 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004161 }
4162
Johan Hedberge3846622013-01-09 15:29:33 +02004163 err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0, &cp->addr,
4164 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004165
4166failed:
4167 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004168 return err;
4169}
4170
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004171static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004172 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004173{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004174 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004175 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004176 int err;
4177
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004178 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004179
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004180 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004181 return cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4182 MGMT_STATUS_INVALID_PARAMS,
4183 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004184
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004185 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004186
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004187 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4188 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004189 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004190 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004191 goto done;
4192 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004193
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004194 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4195 sk);
4196 status = MGMT_STATUS_SUCCESS;
4197
4198done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004199 err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004200 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004201
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004202 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004203
4204 return err;
4205}
4206
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004207static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004208 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004209{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004210 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004211 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004212 int err;
4213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004214 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004215
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004216 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg5d0846d2013-01-20 14:27:22 +02004217 return cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4218 MGMT_STATUS_INVALID_PARAMS,
4219 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004220
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004221 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004222
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004223 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4224 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004225 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004226 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004227 goto done;
4228 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004229
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004230 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4231 sk);
4232 status = MGMT_STATUS_SUCCESS;
4233
4234done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004235 err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004236 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004237
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004238 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004239
4240 return err;
4241}
4242
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004243static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4244 u16 len)
4245{
4246 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004247 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004248 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004249 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004250
4251 BT_DBG("%s", hdev->name);
4252
Szymon Jancc72d4b82012-03-16 16:02:57 +01004253 source = __le16_to_cpu(cp->source);
4254
4255 if (source > 0x0002)
4256 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4257 MGMT_STATUS_INVALID_PARAMS);
4258
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004259 hci_dev_lock(hdev);
4260
Szymon Jancc72d4b82012-03-16 16:02:57 +01004261 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004262 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4263 hdev->devid_product = __le16_to_cpu(cp->product);
4264 hdev->devid_version = __le16_to_cpu(cp->version);
4265
4266 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0, NULL, 0);
4267
Johan Hedberg890ea892013-03-15 17:06:52 -05004268 hci_req_init(&req, hdev);
4269 update_eir(&req);
4270 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004271
4272 hci_dev_unlock(hdev);
4273
4274 return err;
4275}
4276
Johan Hedberg4375f102013-09-25 13:26:10 +03004277static void set_advertising_complete(struct hci_dev *hdev, u8 status)
4278{
4279 struct cmd_lookup match = { NULL, hdev };
4280
4281 if (status) {
4282 u8 mgmt_err = mgmt_status(status);
4283
4284 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4285 cmd_status_rsp, &mgmt_err);
4286 return;
4287 }
4288
Johan Hedbergc93bd152014-07-08 15:07:48 +03004289 if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
4290 set_bit(HCI_ADVERTISING, &hdev->dev_flags);
4291 else
4292 clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
4293
Johan Hedberg4375f102013-09-25 13:26:10 +03004294 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4295 &match);
4296
4297 new_settings(hdev, match.sk);
4298
4299 if (match.sk)
4300 sock_put(match.sk);
4301}
4302
Marcel Holtmann21b51872013-10-10 09:47:53 -07004303static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4304 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004305{
4306 struct mgmt_mode *cp = data;
4307 struct pending_cmd *cmd;
4308 struct hci_request req;
Johan Hedberge6fe7982013-10-02 15:45:22 +03004309 u8 val, enabled, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004310 int err;
4311
4312 BT_DBG("request for %s", hdev->name);
4313
Johan Hedberge6fe7982013-10-02 15:45:22 +03004314 status = mgmt_le_support(hdev);
4315 if (status)
Johan Hedberg4375f102013-09-25 13:26:10 +03004316 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
Johan Hedberge6fe7982013-10-02 15:45:22 +03004317 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004318
4319 if (cp->val != 0x00 && cp->val != 0x01)
4320 return cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4321 MGMT_STATUS_INVALID_PARAMS);
4322
4323 hci_dev_lock(hdev);
4324
4325 val = !!cp->val;
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004326 enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004327
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004328 /* The following conditions are ones which mean that we should
4329 * not do any HCI communication but directly send a mgmt
4330 * response to user space (after toggling the flag if
4331 * necessary).
4332 */
4333 if (!hdev_is_powered(hdev) || val == enabled ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004334 hci_conn_num(hdev, LE_LINK) > 0 ||
4335 (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4336 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Johan Hedberg4375f102013-09-25 13:26:10 +03004337 bool changed = false;
4338
Johan Hedbergf3d3444a2013-10-05 12:01:04 +02004339 if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
4340 change_bit(HCI_ADVERTISING, &hdev->dev_flags);
Johan Hedberg4375f102013-09-25 13:26:10 +03004341 changed = true;
4342 }
4343
4344 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4345 if (err < 0)
4346 goto unlock;
4347
4348 if (changed)
4349 err = new_settings(hdev, sk);
4350
4351 goto unlock;
4352 }
4353
4354 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4355 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
4356 err = cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4357 MGMT_STATUS_BUSY);
4358 goto unlock;
4359 }
4360
4361 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4362 if (!cmd) {
4363 err = -ENOMEM;
4364 goto unlock;
4365 }
4366
4367 hci_req_init(&req, hdev);
4368
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004369 if (val)
4370 enable_advertising(&req);
4371 else
4372 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004373
4374 err = hci_req_run(&req, set_advertising_complete);
4375 if (err < 0)
4376 mgmt_pending_remove(cmd);
4377
4378unlock:
4379 hci_dev_unlock(hdev);
4380 return err;
4381}
4382
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004383static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4384 void *data, u16 len)
4385{
4386 struct mgmt_cp_set_static_address *cp = data;
4387 int err;
4388
4389 BT_DBG("%s", hdev->name);
4390
Marcel Holtmann62af4442013-10-02 22:10:32 -07004391 if (!lmp_le_capable(hdev))
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004392 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann62af4442013-10-02 22:10:32 -07004393 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004394
4395 if (hdev_is_powered(hdev))
4396 return cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4397 MGMT_STATUS_REJECTED);
4398
4399 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4400 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
4401 return cmd_status(sk, hdev->id,
4402 MGMT_OP_SET_STATIC_ADDRESS,
4403 MGMT_STATUS_INVALID_PARAMS);
4404
4405 /* Two most significant bits shall be set */
4406 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
4407 return cmd_status(sk, hdev->id,
4408 MGMT_OP_SET_STATIC_ADDRESS,
4409 MGMT_STATUS_INVALID_PARAMS);
4410 }
4411
4412 hci_dev_lock(hdev);
4413
4414 bacpy(&hdev->static_addr, &cp->bdaddr);
4415
4416 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS, 0, NULL, 0);
4417
4418 hci_dev_unlock(hdev);
4419
4420 return err;
4421}
4422
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004423static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4424 void *data, u16 len)
4425{
4426 struct mgmt_cp_set_scan_params *cp = data;
4427 __u16 interval, window;
4428 int err;
4429
4430 BT_DBG("%s", hdev->name);
4431
4432 if (!lmp_le_capable(hdev))
4433 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4434 MGMT_STATUS_NOT_SUPPORTED);
4435
4436 interval = __le16_to_cpu(cp->interval);
4437
4438 if (interval < 0x0004 || interval > 0x4000)
4439 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4440 MGMT_STATUS_INVALID_PARAMS);
4441
4442 window = __le16_to_cpu(cp->window);
4443
4444 if (window < 0x0004 || window > 0x4000)
4445 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4446 MGMT_STATUS_INVALID_PARAMS);
4447
Marcel Holtmann899e1072013-10-14 09:55:32 -07004448 if (window > interval)
4449 return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4450 MGMT_STATUS_INVALID_PARAMS);
4451
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004452 hci_dev_lock(hdev);
4453
4454 hdev->le_scan_interval = interval;
4455 hdev->le_scan_window = window;
4456
4457 err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0);
4458
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004459 /* If background scan is running, restart it so new parameters are
4460 * loaded.
4461 */
4462 if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) &&
4463 hdev->discovery.state == DISCOVERY_STOPPED) {
4464 struct hci_request req;
4465
4466 hci_req_init(&req, hdev);
4467
4468 hci_req_add_le_scan_disable(&req);
4469 hci_req_add_le_passive_scan(&req);
4470
4471 hci_req_run(&req, NULL);
4472 }
4473
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004474 hci_dev_unlock(hdev);
4475
4476 return err;
4477}
4478
Johan Hedberg33e38b32013-03-15 17:07:05 -05004479static void fast_connectable_complete(struct hci_dev *hdev, u8 status)
4480{
4481 struct pending_cmd *cmd;
4482
4483 BT_DBG("status 0x%02x", status);
4484
4485 hci_dev_lock(hdev);
4486
4487 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4488 if (!cmd)
4489 goto unlock;
4490
4491 if (status) {
4492 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4493 mgmt_status(status));
4494 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004495 struct mgmt_mode *cp = cmd->param;
4496
4497 if (cp->val)
4498 set_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4499 else
4500 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4501
Johan Hedberg33e38b32013-03-15 17:07:05 -05004502 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4503 new_settings(hdev, cmd->sk);
4504 }
4505
4506 mgmt_pending_remove(cmd);
4507
4508unlock:
4509 hci_dev_unlock(hdev);
4510}
4511
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004512static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004513 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004514{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004515 struct mgmt_mode *cp = data;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004516 struct pending_cmd *cmd;
4517 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004518 int err;
4519
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004520 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004521
Johan Hedberg56f87902013-10-02 13:43:13 +03004522 if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) ||
4523 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberg33c525c2012-10-24 21:11:58 +03004524 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4525 MGMT_STATUS_NOT_SUPPORTED);
4526
Johan Hedberga7e80f22013-01-09 16:05:19 +02004527 if (cp->val != 0x00 && cp->val != 0x01)
4528 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4529 MGMT_STATUS_INVALID_PARAMS);
4530
Johan Hedberg5400c042012-02-21 16:40:33 +02004531 if (!hdev_is_powered(hdev))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004532 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004533 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5400c042012-02-21 16:40:33 +02004534
4535 if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004536 return cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004537 MGMT_STATUS_REJECTED);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004538
4539 hci_dev_lock(hdev);
4540
Johan Hedberg05cbf292013-03-15 17:07:07 -05004541 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
4542 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4543 MGMT_STATUS_BUSY);
4544 goto unlock;
4545 }
4546
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004547 if (!!cp->val == test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) {
4548 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4549 hdev);
4550 goto unlock;
4551 }
4552
Johan Hedberg33e38b32013-03-15 17:07:05 -05004553 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4554 data, len);
4555 if (!cmd) {
4556 err = -ENOMEM;
4557 goto unlock;
4558 }
4559
4560 hci_req_init(&req, hdev);
4561
Johan Hedberg406d7802013-03-15 17:07:09 -05004562 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004563
4564 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004565 if (err < 0) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004566 err = cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004567 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004568 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004569 }
4570
Johan Hedberg33e38b32013-03-15 17:07:05 -05004571unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004572 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004573
Antti Julkuf6422ec2011-06-22 13:11:56 +03004574 return err;
4575}
4576
Johan Hedberg0663ca22013-10-02 13:43:14 +03004577static void set_bredr_complete(struct hci_dev *hdev, u8 status)
4578{
4579 struct pending_cmd *cmd;
4580
4581 BT_DBG("status 0x%02x", status);
4582
4583 hci_dev_lock(hdev);
4584
4585 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4586 if (!cmd)
4587 goto unlock;
4588
4589 if (status) {
4590 u8 mgmt_err = mgmt_status(status);
4591
4592 /* We need to restore the flag if related HCI commands
4593 * failed.
4594 */
4595 clear_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4596
4597 cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
4598 } else {
4599 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4600 new_settings(hdev, cmd->sk);
4601 }
4602
4603 mgmt_pending_remove(cmd);
4604
4605unlock:
4606 hci_dev_unlock(hdev);
4607}
4608
4609static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4610{
4611 struct mgmt_mode *cp = data;
4612 struct pending_cmd *cmd;
4613 struct hci_request req;
4614 int err;
4615
4616 BT_DBG("request for %s", hdev->name);
4617
4618 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
4619 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4620 MGMT_STATUS_NOT_SUPPORTED);
4621
4622 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
4623 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4624 MGMT_STATUS_REJECTED);
4625
4626 if (cp->val != 0x00 && cp->val != 0x01)
4627 return cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4628 MGMT_STATUS_INVALID_PARAMS);
4629
4630 hci_dev_lock(hdev);
4631
4632 if (cp->val == test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
4633 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4634 goto unlock;
4635 }
4636
4637 if (!hdev_is_powered(hdev)) {
4638 if (!cp->val) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004639 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
4640 clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
4641 clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
4642 clear_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags);
4643 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
4644 }
4645
4646 change_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4647
4648 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4649 if (err < 0)
4650 goto unlock;
4651
4652 err = new_settings(hdev, sk);
4653 goto unlock;
4654 }
4655
4656 /* Reject disabling when powered on */
4657 if (!cp->val) {
4658 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4659 MGMT_STATUS_REJECTED);
4660 goto unlock;
4661 }
4662
4663 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
4664 err = cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4665 MGMT_STATUS_BUSY);
4666 goto unlock;
4667 }
4668
4669 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4670 if (!cmd) {
4671 err = -ENOMEM;
4672 goto unlock;
4673 }
4674
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004675 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004676 * generates the correct flags.
4677 */
4678 set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
4679
4680 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004681
Johan Hedberg432df052014-08-01 11:13:31 +03004682 write_fast_connectable(&req, false);
4683 hci_update_page_scan(hdev, &req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004684
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004685 /* Since only the advertising data flags will change, there
4686 * is no need to update the scan response data.
4687 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004688 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004689
Johan Hedberg0663ca22013-10-02 13:43:14 +03004690 err = hci_req_run(&req, set_bredr_complete);
4691 if (err < 0)
4692 mgmt_pending_remove(cmd);
4693
4694unlock:
4695 hci_dev_unlock(hdev);
4696 return err;
4697}
4698
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004699static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4700 void *data, u16 len)
4701{
4702 struct mgmt_mode *cp = data;
4703 struct pending_cmd *cmd;
Johan Hedberga3209692014-05-26 11:23:35 +03004704 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004705 int err;
4706
4707 BT_DBG("request for %s", hdev->name);
4708
Johan Hedberga3209692014-05-26 11:23:35 +03004709 if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
4710 !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004711 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4712 MGMT_STATUS_NOT_SUPPORTED);
4713
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004714 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004715 return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4716 MGMT_STATUS_INVALID_PARAMS);
4717
4718 hci_dev_lock(hdev);
4719
Johan Hedberga3209692014-05-26 11:23:35 +03004720 if (!hdev_is_powered(hdev) ||
4721 (!lmp_sc_capable(hdev) &&
4722 !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
4723 !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004724 bool changed;
4725
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004726 if (cp->val) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004727 changed = !test_and_set_bit(HCI_SC_ENABLED,
4728 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004729 if (cp->val == 0x02)
4730 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4731 else
4732 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4733 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004734 changed = test_and_clear_bit(HCI_SC_ENABLED,
4735 &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004736 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4737 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004738
4739 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4740 if (err < 0)
4741 goto failed;
4742
4743 if (changed)
4744 err = new_settings(hdev, sk);
4745
4746 goto failed;
4747 }
4748
4749 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
4750 err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4751 MGMT_STATUS_BUSY);
4752 goto failed;
4753 }
4754
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004755 val = !!cp->val;
4756
4757 if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
4758 (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004759 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4760 goto failed;
4761 }
4762
4763 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
4764 if (!cmd) {
4765 err = -ENOMEM;
4766 goto failed;
4767 }
4768
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004769 err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004770 if (err < 0) {
4771 mgmt_pending_remove(cmd);
4772 goto failed;
4773 }
4774
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004775 if (cp->val == 0x02)
4776 set_bit(HCI_SC_ONLY, &hdev->dev_flags);
4777 else
4778 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
4779
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004780failed:
4781 hci_dev_unlock(hdev);
4782 return err;
4783}
4784
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004785static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
4786 void *data, u16 len)
4787{
4788 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03004789 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004790 int err;
4791
4792 BT_DBG("request for %s", hdev->name);
4793
Johan Hedbergb97109792014-06-24 14:00:28 +03004794 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004795 return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
4796 MGMT_STATUS_INVALID_PARAMS);
4797
4798 hci_dev_lock(hdev);
4799
4800 if (cp->val)
Johan Hedberg0663b292014-06-24 13:15:50 +03004801 changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS,
4802 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004803 else
Johan Hedberg0663b292014-06-24 13:15:50 +03004804 changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS,
4805 &hdev->dev_flags);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004806
Johan Hedbergb97109792014-06-24 14:00:28 +03004807 if (cp->val == 0x02)
4808 use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS,
4809 &hdev->dev_flags);
4810 else
4811 use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS,
4812 &hdev->dev_flags);
4813
4814 if (hdev_is_powered(hdev) && use_changed &&
4815 test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
4816 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
4817 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
4818 sizeof(mode), &mode);
4819 }
4820
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08004821 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
4822 if (err < 0)
4823 goto unlock;
4824
4825 if (changed)
4826 err = new_settings(hdev, sk);
4827
4828unlock:
4829 hci_dev_unlock(hdev);
4830 return err;
4831}
4832
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004833static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4834 u16 len)
4835{
4836 struct mgmt_cp_set_privacy *cp = cp_data;
4837 bool changed;
4838 int err;
4839
4840 BT_DBG("request for %s", hdev->name);
4841
4842 if (!lmp_le_capable(hdev))
4843 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4844 MGMT_STATUS_NOT_SUPPORTED);
4845
4846 if (cp->privacy != 0x00 && cp->privacy != 0x01)
4847 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4848 MGMT_STATUS_INVALID_PARAMS);
4849
4850 if (hdev_is_powered(hdev))
4851 return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
4852 MGMT_STATUS_REJECTED);
4853
4854 hci_dev_lock(hdev);
4855
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02004856 /* If user space supports this command it is also expected to
4857 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
4858 */
4859 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4860
Johan Hedberg62b04cd2014-02-23 19:42:27 +02004861 if (cp->privacy) {
4862 changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags);
4863 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
4864 set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4865 } else {
4866 changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags);
4867 memset(hdev->irk, 0, sizeof(hdev->irk));
4868 clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags);
4869 }
4870
4871 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
4872 if (err < 0)
4873 goto unlock;
4874
4875 if (changed)
4876 err = new_settings(hdev, sk);
4877
4878unlock:
4879 hci_dev_unlock(hdev);
4880 return err;
4881}
4882
Johan Hedberg41edf162014-02-18 10:19:35 +02004883static bool irk_is_valid(struct mgmt_irk_info *irk)
4884{
4885 switch (irk->addr.type) {
4886 case BDADDR_LE_PUBLIC:
4887 return true;
4888
4889 case BDADDR_LE_RANDOM:
4890 /* Two most significant bits shall be set */
4891 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4892 return false;
4893 return true;
4894 }
4895
4896 return false;
4897}
4898
4899static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
4900 u16 len)
4901{
4902 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004903 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
4904 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02004905 u16 irk_count, expected_len;
4906 int i, err;
4907
4908 BT_DBG("request for %s", hdev->name);
4909
4910 if (!lmp_le_capable(hdev))
4911 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4912 MGMT_STATUS_NOT_SUPPORTED);
4913
4914 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03004915 if (irk_count > max_irk_count) {
4916 BT_ERR("load_irks: too big irk_count value %u", irk_count);
4917 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4918 MGMT_STATUS_INVALID_PARAMS);
4919 }
Johan Hedberg41edf162014-02-18 10:19:35 +02004920
4921 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
4922 if (expected_len != len) {
4923 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02004924 expected_len, len);
Johan Hedberg41edf162014-02-18 10:19:35 +02004925 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
4926 MGMT_STATUS_INVALID_PARAMS);
4927 }
4928
4929 BT_DBG("%s irk_count %u", hdev->name, irk_count);
4930
4931 for (i = 0; i < irk_count; i++) {
4932 struct mgmt_irk_info *key = &cp->irks[i];
4933
4934 if (!irk_is_valid(key))
4935 return cmd_status(sk, hdev->id,
4936 MGMT_OP_LOAD_IRKS,
4937 MGMT_STATUS_INVALID_PARAMS);
4938 }
4939
4940 hci_dev_lock(hdev);
4941
4942 hci_smp_irks_clear(hdev);
4943
4944 for (i = 0; i < irk_count; i++) {
4945 struct mgmt_irk_info *irk = &cp->irks[i];
4946 u8 addr_type;
4947
4948 if (irk->addr.type == BDADDR_LE_PUBLIC)
4949 addr_type = ADDR_LE_DEV_PUBLIC;
4950 else
4951 addr_type = ADDR_LE_DEV_RANDOM;
4952
4953 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
4954 BDADDR_ANY);
4955 }
4956
4957 set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags);
4958
4959 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
4960
4961 hci_dev_unlock(hdev);
4962
4963 return err;
4964}
4965
Johan Hedberg3f706b72013-01-20 14:27:16 +02004966static bool ltk_is_valid(struct mgmt_ltk_info *key)
4967{
4968 if (key->master != 0x00 && key->master != 0x01)
4969 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08004970
4971 switch (key->addr.type) {
4972 case BDADDR_LE_PUBLIC:
4973 return true;
4974
4975 case BDADDR_LE_RANDOM:
4976 /* Two most significant bits shall be set */
4977 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
4978 return false;
4979 return true;
4980 }
4981
4982 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02004983}
4984
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004985static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004986 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004987{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004988 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03004989 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
4990 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004991 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02004992 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03004993
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07004994 BT_DBG("request for %s", hdev->name);
4995
4996 if (!lmp_le_capable(hdev))
4997 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
4998 MGMT_STATUS_NOT_SUPPORTED);
4999
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005000 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005001 if (key_count > max_key_count) {
5002 BT_ERR("load_ltks: too big key_count value %u", key_count);
5003 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5004 MGMT_STATUS_INVALID_PARAMS);
5005 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005006
5007 expected_len = sizeof(*cp) + key_count *
5008 sizeof(struct mgmt_ltk_info);
5009 if (expected_len != len) {
5010 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005011 expected_len, len);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005012 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
Johan Hedberge57e6192013-01-20 14:27:14 +02005013 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005014 }
5015
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005016 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005017
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005018 for (i = 0; i < key_count; i++) {
5019 struct mgmt_ltk_info *key = &cp->keys[i];
5020
Johan Hedberg3f706b72013-01-20 14:27:16 +02005021 if (!ltk_is_valid(key))
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005022 return cmd_status(sk, hdev->id,
5023 MGMT_OP_LOAD_LONG_TERM_KEYS,
5024 MGMT_STATUS_INVALID_PARAMS);
5025 }
5026
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005027 hci_dev_lock(hdev);
5028
5029 hci_smp_ltks_clear(hdev);
5030
5031 for (i = 0; i < key_count; i++) {
5032 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005033 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005034
5035 if (key->addr.type == BDADDR_LE_PUBLIC)
5036 addr_type = ADDR_LE_DEV_PUBLIC;
5037 else
5038 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005039
Johan Hedberg61b43352014-05-29 19:36:53 +03005040 switch (key->type) {
5041 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005042 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005043 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005044 break;
5045 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005046 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005047 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005048 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005049 case MGMT_LTK_P256_UNAUTH:
5050 authenticated = 0x00;
5051 type = SMP_LTK_P256;
5052 break;
5053 case MGMT_LTK_P256_AUTH:
5054 authenticated = 0x01;
5055 type = SMP_LTK_P256;
5056 break;
5057 case MGMT_LTK_P256_DEBUG:
5058 authenticated = 0x00;
5059 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005060 default:
5061 continue;
5062 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005063
Johan Hedberg35d70272014-02-19 14:57:47 +02005064 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005065 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005066 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005067 }
5068
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005069 err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
5070 NULL, 0);
5071
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005072 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005073
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005074 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005075}
5076
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005077struct cmd_conn_lookup {
5078 struct hci_conn *conn;
5079 bool valid_tx_power;
5080 u8 mgmt_status;
5081};
5082
5083static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5084{
5085 struct cmd_conn_lookup *match = data;
5086 struct mgmt_cp_get_conn_info *cp;
5087 struct mgmt_rp_get_conn_info rp;
5088 struct hci_conn *conn = cmd->user_data;
5089
5090 if (conn != match->conn)
5091 return;
5092
5093 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5094
5095 memset(&rp, 0, sizeof(rp));
5096 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5097 rp.addr.type = cp->addr.type;
5098
5099 if (!match->mgmt_status) {
5100 rp.rssi = conn->rssi;
5101
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005102 if (match->valid_tx_power) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005103 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005104 rp.max_tx_power = conn->max_tx_power;
5105 } else {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005106 rp.tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005107 rp.max_tx_power = HCI_TX_POWER_INVALID;
5108 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005109 }
5110
5111 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5112 match->mgmt_status, &rp, sizeof(rp));
5113
5114 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005115 hci_conn_put(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005116
5117 mgmt_pending_remove(cmd);
5118}
5119
5120static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5121{
5122 struct hci_cp_read_rssi *cp;
5123 struct hci_conn *conn;
5124 struct cmd_conn_lookup match;
5125 u16 handle;
5126
5127 BT_DBG("status 0x%02x", status);
5128
5129 hci_dev_lock(hdev);
5130
5131 /* TX power data is valid in case request completed successfully,
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005132 * otherwise we assume it's not valid. At the moment we assume that
5133 * either both or none of current and max values are valid to keep code
5134 * simple.
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005135 */
5136 match.valid_tx_power = !status;
5137
5138 /* Commands sent in request are either Read RSSI or Read Transmit Power
5139 * Level so we check which one was last sent to retrieve connection
5140 * handle. Both commands have handle as first parameter so it's safe to
5141 * cast data on the same command struct.
5142 *
5143 * First command sent is always Read RSSI and we fail only if it fails.
5144 * In other case we simply override error to indicate success as we
5145 * already remembered if TX power value is actually valid.
5146 */
5147 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5148 if (!cp) {
5149 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5150 status = 0;
5151 }
5152
5153 if (!cp) {
5154 BT_ERR("invalid sent_cmd in response");
5155 goto unlock;
5156 }
5157
5158 handle = __le16_to_cpu(cp->handle);
5159 conn = hci_conn_hash_lookup_handle(hdev, handle);
5160 if (!conn) {
5161 BT_ERR("unknown handle (%d) in response", handle);
5162 goto unlock;
5163 }
5164
5165 match.conn = conn;
5166 match.mgmt_status = mgmt_status(status);
5167
5168 /* Cache refresh is complete, now reply for mgmt request for given
5169 * connection only.
5170 */
5171 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5172 get_conn_info_complete, &match);
5173
5174unlock:
5175 hci_dev_unlock(hdev);
5176}
5177
5178static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5179 u16 len)
5180{
5181 struct mgmt_cp_get_conn_info *cp = data;
5182 struct mgmt_rp_get_conn_info rp;
5183 struct hci_conn *conn;
5184 unsigned long conn_info_age;
5185 int err = 0;
5186
5187 BT_DBG("%s", hdev->name);
5188
5189 memset(&rp, 0, sizeof(rp));
5190 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5191 rp.addr.type = cp->addr.type;
5192
5193 if (!bdaddr_type_is_valid(cp->addr.type))
5194 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5195 MGMT_STATUS_INVALID_PARAMS,
5196 &rp, sizeof(rp));
5197
5198 hci_dev_lock(hdev);
5199
5200 if (!hdev_is_powered(hdev)) {
5201 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5202 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5203 goto unlock;
5204 }
5205
5206 if (cp->addr.type == BDADDR_BREDR)
5207 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5208 &cp->addr.bdaddr);
5209 else
5210 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5211
5212 if (!conn || conn->state != BT_CONNECTED) {
5213 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5214 MGMT_STATUS_NOT_CONNECTED, &rp, sizeof(rp));
5215 goto unlock;
5216 }
5217
5218 /* To avoid client trying to guess when to poll again for information we
5219 * calculate conn info age as random value between min/max set in hdev.
5220 */
5221 conn_info_age = hdev->conn_info_min_age +
5222 prandom_u32_max(hdev->conn_info_max_age -
5223 hdev->conn_info_min_age);
5224
5225 /* Query controller to refresh cached values if they are too old or were
5226 * never read.
5227 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005228 if (time_after(jiffies, conn->conn_info_timestamp +
5229 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005230 !conn->conn_info_timestamp) {
5231 struct hci_request req;
5232 struct hci_cp_read_tx_power req_txp_cp;
5233 struct hci_cp_read_rssi req_rssi_cp;
5234 struct pending_cmd *cmd;
5235
5236 hci_req_init(&req, hdev);
5237 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5238 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5239 &req_rssi_cp);
5240
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005241 /* For LE links TX power does not change thus we don't need to
5242 * query for it once value is known.
5243 */
5244 if (!bdaddr_type_is_le(cp->addr.type) ||
5245 conn->tx_power == HCI_TX_POWER_INVALID) {
5246 req_txp_cp.handle = cpu_to_le16(conn->handle);
5247 req_txp_cp.type = 0x00;
5248 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5249 sizeof(req_txp_cp), &req_txp_cp);
5250 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005251
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005252 /* Max TX power needs to be read only once per connection */
5253 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5254 req_txp_cp.handle = cpu_to_le16(conn->handle);
5255 req_txp_cp.type = 0x01;
5256 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5257 sizeof(req_txp_cp), &req_txp_cp);
5258 }
5259
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005260 err = hci_req_run(&req, conn_info_refresh_complete);
5261 if (err < 0)
5262 goto unlock;
5263
5264 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5265 data, len);
5266 if (!cmd) {
5267 err = -ENOMEM;
5268 goto unlock;
5269 }
5270
5271 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005272 cmd->user_data = hci_conn_get(conn);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005273
5274 conn->conn_info_timestamp = jiffies;
5275 } else {
5276 /* Cache is valid, just reply with values cached in hci_conn */
5277 rp.rssi = conn->rssi;
5278 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005279 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005280
5281 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5282 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
5283 }
5284
5285unlock:
5286 hci_dev_unlock(hdev);
5287 return err;
5288}
5289
Johan Hedberg69487372014-12-05 13:36:07 +02005290static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
5291{
5292 struct hci_conn *conn = cmd->user_data;
5293 struct mgmt_rp_get_clock_info rp;
5294 struct hci_dev *hdev;
5295
5296 memset(&rp, 0, sizeof(rp));
5297 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5298
5299 if (status)
5300 goto complete;
5301
5302 hdev = hci_dev_get(cmd->index);
5303 if (hdev) {
5304 rp.local_clock = cpu_to_le32(hdev->clock);
5305 hci_dev_put(hdev);
5306 }
5307
5308 if (conn) {
5309 rp.piconet_clock = cpu_to_le32(conn->clock);
5310 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5311 }
5312
5313complete:
5314 cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
5315
5316 if (conn) {
5317 hci_conn_drop(conn);
5318 hci_conn_put(conn);
5319 }
5320}
5321
Johan Hedberg95868422014-06-28 17:54:07 +03005322static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
5323{
Johan Hedberg95868422014-06-28 17:54:07 +03005324 struct hci_cp_read_clock *hci_cp;
5325 struct pending_cmd *cmd;
5326 struct hci_conn *conn;
5327
5328 BT_DBG("%s status %u", hdev->name, status);
5329
5330 hci_dev_lock(hdev);
5331
5332 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5333 if (!hci_cp)
5334 goto unlock;
5335
5336 if (hci_cp->which) {
5337 u16 handle = __le16_to_cpu(hci_cp->handle);
5338 conn = hci_conn_hash_lookup_handle(hdev, handle);
5339 } else {
5340 conn = NULL;
5341 }
5342
5343 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5344 if (!cmd)
5345 goto unlock;
5346
Johan Hedberg69487372014-12-05 13:36:07 +02005347 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005348 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005349
5350unlock:
5351 hci_dev_unlock(hdev);
5352}
5353
5354static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5355 u16 len)
5356{
5357 struct mgmt_cp_get_clock_info *cp = data;
5358 struct mgmt_rp_get_clock_info rp;
5359 struct hci_cp_read_clock hci_cp;
5360 struct pending_cmd *cmd;
5361 struct hci_request req;
5362 struct hci_conn *conn;
5363 int err;
5364
5365 BT_DBG("%s", hdev->name);
5366
5367 memset(&rp, 0, sizeof(rp));
5368 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5369 rp.addr.type = cp->addr.type;
5370
5371 if (cp->addr.type != BDADDR_BREDR)
5372 return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5373 MGMT_STATUS_INVALID_PARAMS,
5374 &rp, sizeof(rp));
5375
5376 hci_dev_lock(hdev);
5377
5378 if (!hdev_is_powered(hdev)) {
5379 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5380 MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp));
5381 goto unlock;
5382 }
5383
5384 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5385 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5386 &cp->addr.bdaddr);
5387 if (!conn || conn->state != BT_CONNECTED) {
5388 err = cmd_complete(sk, hdev->id,
5389 MGMT_OP_GET_CLOCK_INFO,
5390 MGMT_STATUS_NOT_CONNECTED,
5391 &rp, sizeof(rp));
5392 goto unlock;
5393 }
5394 } else {
5395 conn = NULL;
5396 }
5397
5398 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5399 if (!cmd) {
5400 err = -ENOMEM;
5401 goto unlock;
5402 }
5403
Johan Hedberg69487372014-12-05 13:36:07 +02005404 cmd->cmd_complete = clock_info_cmd_complete;
5405
Johan Hedberg95868422014-06-28 17:54:07 +03005406 hci_req_init(&req, hdev);
5407
5408 memset(&hci_cp, 0, sizeof(hci_cp));
5409 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5410
5411 if (conn) {
5412 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005413 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005414
5415 hci_cp.handle = cpu_to_le16(conn->handle);
5416 hci_cp.which = 0x01; /* Piconet clock */
5417 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5418 }
5419
5420 err = hci_req_run(&req, get_clock_info_complete);
5421 if (err < 0)
5422 mgmt_pending_remove(cmd);
5423
5424unlock:
5425 hci_dev_unlock(hdev);
5426 return err;
5427}
5428
Marcel Holtmann8afef092014-06-29 22:28:34 +02005429static void device_added(struct sock *sk, struct hci_dev *hdev,
5430 bdaddr_t *bdaddr, u8 type, u8 action)
5431{
5432 struct mgmt_ev_device_added ev;
5433
5434 bacpy(&ev.addr.bdaddr, bdaddr);
5435 ev.addr.type = type;
5436 ev.action = action;
5437
5438 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5439}
5440
Marcel Holtmann2faade52014-06-29 19:44:03 +02005441static int add_device(struct sock *sk, struct hci_dev *hdev,
5442 void *data, u16 len)
5443{
5444 struct mgmt_cp_add_device *cp = data;
5445 u8 auto_conn, addr_type;
5446 int err;
5447
5448 BT_DBG("%s", hdev->name);
5449
Johan Hedberg66593582014-07-09 12:59:14 +03005450 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005451 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
5452 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5453 MGMT_STATUS_INVALID_PARAMS,
5454 &cp->addr, sizeof(cp->addr));
5455
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005456 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005457 return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5458 MGMT_STATUS_INVALID_PARAMS,
5459 &cp->addr, sizeof(cp->addr));
5460
5461 hci_dev_lock(hdev);
5462
Johan Hedberg66593582014-07-09 12:59:14 +03005463 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005464 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005465 if (cp->action != 0x01) {
5466 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5467 MGMT_STATUS_INVALID_PARAMS,
5468 &cp->addr, sizeof(cp->addr));
5469 goto unlock;
5470 }
5471
5472 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5473 cp->addr.type);
5474 if (err)
5475 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005476
Johan Hedberg432df052014-08-01 11:13:31 +03005477 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005478
Johan Hedberg66593582014-07-09 12:59:14 +03005479 goto added;
5480 }
5481
Marcel Holtmann2faade52014-06-29 19:44:03 +02005482 if (cp->addr.type == BDADDR_LE_PUBLIC)
5483 addr_type = ADDR_LE_DEV_PUBLIC;
5484 else
5485 addr_type = ADDR_LE_DEV_RANDOM;
5486
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005487 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005488 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005489 else if (cp->action == 0x01)
5490 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005491 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005492 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005493
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005494 /* If the connection parameters don't exist for this device,
5495 * they will be created and configured with defaults.
5496 */
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005497 if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
5498 auto_conn) < 0) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005499 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5500 MGMT_STATUS_FAILED,
5501 &cp->addr, sizeof(cp->addr));
5502 goto unlock;
5503 }
5504
Johan Hedberg66593582014-07-09 12:59:14 +03005505added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005506 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5507
Marcel Holtmann2faade52014-06-29 19:44:03 +02005508 err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5509 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5510
5511unlock:
5512 hci_dev_unlock(hdev);
5513 return err;
5514}
5515
Marcel Holtmann8afef092014-06-29 22:28:34 +02005516static void device_removed(struct sock *sk, struct hci_dev *hdev,
5517 bdaddr_t *bdaddr, u8 type)
5518{
5519 struct mgmt_ev_device_removed ev;
5520
5521 bacpy(&ev.addr.bdaddr, bdaddr);
5522 ev.addr.type = type;
5523
5524 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5525}
5526
Marcel Holtmann2faade52014-06-29 19:44:03 +02005527static int remove_device(struct sock *sk, struct hci_dev *hdev,
5528 void *data, u16 len)
5529{
5530 struct mgmt_cp_remove_device *cp = data;
5531 int err;
5532
5533 BT_DBG("%s", hdev->name);
5534
5535 hci_dev_lock(hdev);
5536
5537 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005538 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005539 u8 addr_type;
5540
Johan Hedberg66593582014-07-09 12:59:14 +03005541 if (!bdaddr_type_is_valid(cp->addr.type)) {
Marcel Holtmann2faade52014-06-29 19:44:03 +02005542 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5543 MGMT_STATUS_INVALID_PARAMS,
5544 &cp->addr, sizeof(cp->addr));
5545 goto unlock;
5546 }
5547
Johan Hedberg66593582014-07-09 12:59:14 +03005548 if (cp->addr.type == BDADDR_BREDR) {
5549 err = hci_bdaddr_list_del(&hdev->whitelist,
5550 &cp->addr.bdaddr,
5551 cp->addr.type);
5552 if (err) {
5553 err = cmd_complete(sk, hdev->id,
5554 MGMT_OP_REMOVE_DEVICE,
5555 MGMT_STATUS_INVALID_PARAMS,
5556 &cp->addr, sizeof(cp->addr));
5557 goto unlock;
5558 }
5559
Johan Hedberg432df052014-08-01 11:13:31 +03005560 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005561
Johan Hedberg66593582014-07-09 12:59:14 +03005562 device_removed(sk, hdev, &cp->addr.bdaddr,
5563 cp->addr.type);
5564 goto complete;
5565 }
5566
Marcel Holtmann2faade52014-06-29 19:44:03 +02005567 if (cp->addr.type == BDADDR_LE_PUBLIC)
5568 addr_type = ADDR_LE_DEV_PUBLIC;
5569 else
5570 addr_type = ADDR_LE_DEV_RANDOM;
5571
Johan Hedbergc71593d2014-07-02 17:37:28 +03005572 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5573 addr_type);
5574 if (!params) {
5575 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5576 MGMT_STATUS_INVALID_PARAMS,
5577 &cp->addr, sizeof(cp->addr));
5578 goto unlock;
5579 }
5580
5581 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
5582 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5583 MGMT_STATUS_INVALID_PARAMS,
5584 &cp->addr, sizeof(cp->addr));
5585 goto unlock;
5586 }
5587
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005588 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005589 list_del(&params->list);
5590 kfree(params);
Johan Hedberg95305ba2014-07-04 12:37:21 +03005591 hci_update_background_scan(hdev);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005592
5593 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005594 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005595 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005596 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005597
Marcel Holtmann2faade52014-06-29 19:44:03 +02005598 if (cp->addr.type) {
5599 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5600 MGMT_STATUS_INVALID_PARAMS,
5601 &cp->addr, sizeof(cp->addr));
5602 goto unlock;
5603 }
5604
Johan Hedberg66593582014-07-09 12:59:14 +03005605 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5606 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5607 list_del(&b->list);
5608 kfree(b);
5609 }
5610
Johan Hedberg432df052014-08-01 11:13:31 +03005611 hci_update_page_scan(hdev, NULL);
Johan Hedberga3974072014-07-09 12:59:15 +03005612
Johan Hedberg19de0822014-07-06 13:06:51 +03005613 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5614 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5615 continue;
5616 device_removed(sk, hdev, &p->addr, p->addr_type);
5617 list_del(&p->action);
5618 list_del(&p->list);
5619 kfree(p);
5620 }
5621
5622 BT_DBG("All LE connection parameters were removed");
5623
5624 hci_update_background_scan(hdev);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005625 }
5626
Johan Hedberg66593582014-07-09 12:59:14 +03005627complete:
Marcel Holtmann2faade52014-06-29 19:44:03 +02005628 err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
5629 MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr));
5630
5631unlock:
5632 hci_dev_unlock(hdev);
5633 return err;
5634}
5635
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005636static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5637 u16 len)
5638{
5639 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005640 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
5641 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005642 u16 param_count, expected_len;
5643 int i;
5644
5645 if (!lmp_le_capable(hdev))
5646 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5647 MGMT_STATUS_NOT_SUPPORTED);
5648
5649 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005650 if (param_count > max_param_count) {
5651 BT_ERR("load_conn_param: too big param_count value %u",
5652 param_count);
5653 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5654 MGMT_STATUS_INVALID_PARAMS);
5655 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005656
5657 expected_len = sizeof(*cp) + param_count *
5658 sizeof(struct mgmt_conn_param);
5659 if (expected_len != len) {
5660 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5661 expected_len, len);
5662 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5663 MGMT_STATUS_INVALID_PARAMS);
5664 }
5665
5666 BT_DBG("%s param_count %u", hdev->name, param_count);
5667
5668 hci_dev_lock(hdev);
5669
5670 hci_conn_params_clear_disabled(hdev);
5671
5672 for (i = 0; i < param_count; i++) {
5673 struct mgmt_conn_param *param = &cp->params[i];
5674 struct hci_conn_params *hci_param;
5675 u16 min, max, latency, timeout;
5676 u8 addr_type;
5677
5678 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5679 param->addr.type);
5680
5681 if (param->addr.type == BDADDR_LE_PUBLIC) {
5682 addr_type = ADDR_LE_DEV_PUBLIC;
5683 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5684 addr_type = ADDR_LE_DEV_RANDOM;
5685 } else {
5686 BT_ERR("Ignoring invalid connection parameters");
5687 continue;
5688 }
5689
5690 min = le16_to_cpu(param->min_interval);
5691 max = le16_to_cpu(param->max_interval);
5692 latency = le16_to_cpu(param->latency);
5693 timeout = le16_to_cpu(param->timeout);
5694
5695 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5696 min, max, latency, timeout);
5697
5698 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5699 BT_ERR("Ignoring invalid connection parameters");
5700 continue;
5701 }
5702
5703 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5704 addr_type);
5705 if (!hci_param) {
5706 BT_ERR("Failed to add connection parameters");
5707 continue;
5708 }
5709
5710 hci_param->conn_min_interval = min;
5711 hci_param->conn_max_interval = max;
5712 hci_param->conn_latency = latency;
5713 hci_param->supervision_timeout = timeout;
5714 }
5715
5716 hci_dev_unlock(hdev);
5717
5718 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5719}
5720
Marcel Holtmanndbece372014-07-04 18:11:55 +02005721static int set_external_config(struct sock *sk, struct hci_dev *hdev,
5722 void *data, u16 len)
5723{
5724 struct mgmt_cp_set_external_config *cp = data;
5725 bool changed;
5726 int err;
5727
5728 BT_DBG("%s", hdev->name);
5729
5730 if (hdev_is_powered(hdev))
5731 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5732 MGMT_STATUS_REJECTED);
5733
5734 if (cp->config != 0x00 && cp->config != 0x01)
5735 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5736 MGMT_STATUS_INVALID_PARAMS);
5737
5738 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
5739 return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
5740 MGMT_STATUS_NOT_SUPPORTED);
5741
5742 hci_dev_lock(hdev);
5743
5744 if (cp->config)
5745 changed = !test_and_set_bit(HCI_EXT_CONFIGURED,
5746 &hdev->dev_flags);
5747 else
5748 changed = test_and_clear_bit(HCI_EXT_CONFIGURED,
5749 &hdev->dev_flags);
5750
5751 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
5752 if (err < 0)
5753 goto unlock;
5754
5755 if (!changed)
5756 goto unlock;
5757
Marcel Holtmannf4537c02014-07-04 19:06:23 +02005758 err = new_options(hdev, sk);
5759
Marcel Holtmanndbece372014-07-04 18:11:55 +02005760 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) {
5761 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005762
5763 if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) {
5764 set_bit(HCI_CONFIG, &hdev->dev_flags);
5765 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5766
5767 queue_work(hdev->req_workqueue, &hdev->power_on);
5768 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02005769 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005770 mgmt_index_added(hdev);
5771 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02005772 }
5773
5774unlock:
5775 hci_dev_unlock(hdev);
5776 return err;
5777}
5778
Marcel Holtmann9713c172014-07-06 12:11:15 +02005779static int set_public_address(struct sock *sk, struct hci_dev *hdev,
5780 void *data, u16 len)
5781{
5782 struct mgmt_cp_set_public_address *cp = data;
5783 bool changed;
5784 int err;
5785
5786 BT_DBG("%s", hdev->name);
5787
5788 if (hdev_is_powered(hdev))
5789 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5790 MGMT_STATUS_REJECTED);
5791
5792 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
5793 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5794 MGMT_STATUS_INVALID_PARAMS);
5795
5796 if (!hdev->set_bdaddr)
5797 return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
5798 MGMT_STATUS_NOT_SUPPORTED);
5799
5800 hci_dev_lock(hdev);
5801
5802 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
5803 bacpy(&hdev->public_addr, &cp->bdaddr);
5804
5805 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
5806 if (err < 0)
5807 goto unlock;
5808
5809 if (!changed)
5810 goto unlock;
5811
5812 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
5813 err = new_options(hdev, sk);
5814
5815 if (is_configured(hdev)) {
5816 mgmt_index_removed(hdev);
5817
5818 clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags);
5819
5820 set_bit(HCI_CONFIG, &hdev->dev_flags);
5821 set_bit(HCI_AUTO_OFF, &hdev->dev_flags);
5822
5823 queue_work(hdev->req_workqueue, &hdev->power_on);
5824 }
5825
5826unlock:
5827 hci_dev_unlock(hdev);
5828 return err;
5829}
5830
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005831static const struct mgmt_handler {
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005832 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5833 u16 data_len);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005834 bool var_len;
5835 size_t data_len;
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005836} mgmt_handlers[] = {
5837 { NULL }, /* 0x0000 (no command) */
Johan Hedbergbe22b542012-03-01 22:24:41 +02005838 { read_version, false, MGMT_READ_VERSION_SIZE },
5839 { read_commands, false, MGMT_READ_COMMANDS_SIZE },
5840 { read_index_list, false, MGMT_READ_INDEX_LIST_SIZE },
5841 { read_controller_info, false, MGMT_READ_INFO_SIZE },
5842 { set_powered, false, MGMT_SETTING_SIZE },
5843 { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE },
5844 { set_connectable, false, MGMT_SETTING_SIZE },
5845 { set_fast_connectable, false, MGMT_SETTING_SIZE },
Johan Hedbergb2939472014-07-30 09:22:23 +03005846 { set_bondable, false, MGMT_SETTING_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005847 { set_link_security, false, MGMT_SETTING_SIZE },
5848 { set_ssp, false, MGMT_SETTING_SIZE },
5849 { set_hs, false, MGMT_SETTING_SIZE },
5850 { set_le, false, MGMT_SETTING_SIZE },
5851 { set_dev_class, false, MGMT_SET_DEV_CLASS_SIZE },
5852 { set_local_name, false, MGMT_SET_LOCAL_NAME_SIZE },
5853 { add_uuid, false, MGMT_ADD_UUID_SIZE },
5854 { remove_uuid, false, MGMT_REMOVE_UUID_SIZE },
5855 { load_link_keys, true, MGMT_LOAD_LINK_KEYS_SIZE },
5856 { load_long_term_keys, true, MGMT_LOAD_LONG_TERM_KEYS_SIZE },
5857 { disconnect, false, MGMT_DISCONNECT_SIZE },
5858 { get_connections, false, MGMT_GET_CONNECTIONS_SIZE },
5859 { pin_code_reply, false, MGMT_PIN_CODE_REPLY_SIZE },
5860 { pin_code_neg_reply, false, MGMT_PIN_CODE_NEG_REPLY_SIZE },
5861 { set_io_capability, false, MGMT_SET_IO_CAPABILITY_SIZE },
5862 { pair_device, false, MGMT_PAIR_DEVICE_SIZE },
5863 { cancel_pair_device, false, MGMT_CANCEL_PAIR_DEVICE_SIZE },
5864 { unpair_device, false, MGMT_UNPAIR_DEVICE_SIZE },
5865 { user_confirm_reply, false, MGMT_USER_CONFIRM_REPLY_SIZE },
5866 { user_confirm_neg_reply, false, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
5867 { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE },
5868 { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
5869 { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE },
Marcel Holtmannec109112014-01-10 02:07:30 -08005870 { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE },
Johan Hedbergbe22b542012-03-01 22:24:41 +02005871 { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
5872 { start_discovery, false, MGMT_START_DISCOVERY_SIZE },
5873 { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE },
5874 { confirm_name, false, MGMT_CONFIRM_NAME_SIZE },
5875 { block_device, false, MGMT_BLOCK_DEVICE_SIZE },
5876 { unblock_device, false, MGMT_UNBLOCK_DEVICE_SIZE },
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07005877 { set_device_id, false, MGMT_SET_DEVICE_ID_SIZE },
Johan Hedberg4375f102013-09-25 13:26:10 +03005878 { set_advertising, false, MGMT_SETTING_SIZE },
Johan Hedberg0663ca22013-10-02 13:43:14 +03005879 { set_bredr, false, MGMT_SETTING_SIZE },
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07005880 { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE },
Marcel Holtmann14b49b92013-10-11 08:23:20 -07005881 { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE },
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005882 { set_secure_conn, false, MGMT_SETTING_SIZE },
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005883 { set_debug_keys, false, MGMT_SETTING_SIZE },
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005884 { set_privacy, false, MGMT_SET_PRIVACY_SIZE },
Johan Hedberg41edf162014-02-18 10:19:35 +02005885 { load_irks, true, MGMT_LOAD_IRKS_SIZE },
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005886 { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE },
Johan Hedberg95868422014-06-28 17:54:07 +03005887 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
Marcel Holtmann2faade52014-06-29 19:44:03 +02005888 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5889 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005890 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5891 { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE },
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +02005892 { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
Marcel Holtmanndbece372014-07-04 18:11:55 +02005893 { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
Marcel Holtmann9713c172014-07-06 12:11:15 +02005894 { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01005895 { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005896};
5897
Johan Hedberg03811012010-12-08 00:21:06 +02005898int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
5899{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005900 void *buf;
5901 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02005902 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01005903 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005904 struct hci_dev *hdev = NULL;
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +02005905 const struct mgmt_handler *handler;
Johan Hedberg03811012010-12-08 00:21:06 +02005906 int err;
5907
5908 BT_DBG("got %zu bytes", msglen);
5909
5910 if (msglen < sizeof(*hdr))
5911 return -EINVAL;
5912
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03005913 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02005914 if (!buf)
5915 return -ENOMEM;
5916
5917 if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
5918 err = -EFAULT;
5919 goto done;
5920 }
5921
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03005922 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005923 opcode = __le16_to_cpu(hdr->opcode);
5924 index = __le16_to_cpu(hdr->index);
5925 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02005926
5927 if (len != msglen - sizeof(*hdr)) {
5928 err = -EINVAL;
5929 goto done;
5930 }
5931
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005932 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005933 hdev = hci_dev_get(index);
5934 if (!hdev) {
5935 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005936 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005937 goto done;
5938 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005939
Johan Hedbergcebf4cf2013-10-10 18:06:04 +02005940 if (test_bit(HCI_SETUP, &hdev->dev_flags) ||
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02005941 test_bit(HCI_CONFIG, &hdev->dev_flags) ||
Marcel Holtmann4a964402014-07-02 19:10:33 +02005942 test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) {
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07005943 err = cmd_status(sk, index, opcode,
5944 MGMT_STATUS_INVALID_INDEX);
5945 goto done;
5946 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005947
5948 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) &&
Marcel Holtmanndbece372014-07-04 18:11:55 +02005949 opcode != MGMT_OP_READ_CONFIG_INFO &&
Marcel Holtmann9713c172014-07-06 12:11:15 +02005950 opcode != MGMT_OP_SET_EXTERNAL_CONFIG &&
5951 opcode != MGMT_OP_SET_PUBLIC_ADDRESS) {
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02005952 err = cmd_status(sk, index, opcode,
5953 MGMT_STATUS_INVALID_INDEX);
5954 goto done;
5955 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005956 }
5957
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005958 if (opcode >= ARRAY_SIZE(mgmt_handlers) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005959 mgmt_handlers[opcode].func == NULL) {
Johan Hedberg03811012010-12-08 00:21:06 +02005960 BT_DBG("Unknown op %u", opcode);
Johan Hedbergca69b792011-11-11 18:10:00 +02005961 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005962 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005963 goto done;
Johan Hedberg03811012010-12-08 00:21:06 +02005964 }
5965
Marcel Holtmann73d1df22014-07-02 22:10:52 +02005966 if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST ||
5967 opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) {
5968 err = cmd_status(sk, index, opcode,
5969 MGMT_STATUS_INVALID_INDEX);
5970 goto done;
5971 }
5972
5973 if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST &&
5974 opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005975 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005976 MGMT_STATUS_INVALID_INDEX);
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005977 goto done;
5978 }
5979
Johan Hedbergbe22b542012-03-01 22:24:41 +02005980 handler = &mgmt_handlers[opcode];
5981
5982 if ((handler->var_len && len < handler->data_len) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03005983 (!handler->var_len && len != handler->data_len)) {
Johan Hedbergbe22b542012-03-01 22:24:41 +02005984 err = cmd_status(sk, index, opcode,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005985 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02005986 goto done;
5987 }
5988
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02005989 if (hdev)
5990 mgmt_init_hdev(sk, hdev);
5991
5992 cp = buf + sizeof(*hdr);
5993
Johan Hedbergbe22b542012-03-01 22:24:41 +02005994 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02005995 if (err < 0)
5996 goto done;
5997
Johan Hedberg03811012010-12-08 00:21:06 +02005998 err = msglen;
5999
6000done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006001 if (hdev)
6002 hci_dev_put(hdev);
6003
Johan Hedberg03811012010-12-08 00:21:06 +02006004 kfree(buf);
6005 return err;
6006}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006007
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006008void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006009{
Marcel Holtmann1514b892013-10-06 08:25:01 -07006010 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006011 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006012
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006013 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6014 return;
6015
6016 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6017 mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL);
6018 else
6019 mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006020}
6021
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006022void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006023{
Johan Hedberg5f159032012-03-02 03:13:19 +02006024 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006025
Marcel Holtmann1514b892013-10-06 08:25:01 -07006026 if (hdev->dev_type != HCI_BREDR)
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006027 return;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006028
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006029 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6030 return;
6031
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006032 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006033
Marcel Holtmannedd3896b2014-07-02 21:30:55 +02006034 if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
6035 mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
6036 else
6037 mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006038}
6039
Andre Guedes6046dc32014-02-26 20:21:51 -03006040/* This function requires the caller holds hdev->lock */
Johan Hedbergd7347f32014-07-04 12:37:23 +03006041static void restart_le_actions(struct hci_dev *hdev)
Andre Guedes6046dc32014-02-26 20:21:51 -03006042{
6043 struct hci_conn_params *p;
6044
6045 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006046 /* Needed for AUTO_OFF case where might not "really"
6047 * have been powered off.
6048 */
6049 list_del_init(&p->action);
6050
6051 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006052 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006053 case HCI_AUTO_CONN_ALWAYS:
6054 list_add(&p->action, &hdev->pend_le_conns);
6055 break;
6056 case HCI_AUTO_CONN_REPORT:
6057 list_add(&p->action, &hdev->pend_le_reports);
6058 break;
6059 default:
6060 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006061 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006062 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006063
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006064 hci_update_background_scan(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006065}
6066
Johan Hedberg229ab392013-03-15 17:06:53 -05006067static void powered_complete(struct hci_dev *hdev, u8 status)
6068{
6069 struct cmd_lookup match = { NULL, hdev };
6070
6071 BT_DBG("status 0x%02x", status);
6072
6073 hci_dev_lock(hdev);
6074
Johan Hedbergd7347f32014-07-04 12:37:23 +03006075 restart_le_actions(hdev);
Andre Guedes6046dc32014-02-26 20:21:51 -03006076
Johan Hedberg229ab392013-03-15 17:06:53 -05006077 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6078
6079 new_settings(hdev, match.sk);
6080
6081 hci_dev_unlock(hdev);
6082
6083 if (match.sk)
6084 sock_put(match.sk);
6085}
6086
Johan Hedberg70da6242013-03-15 17:06:51 -05006087static int powered_update_hci(struct hci_dev *hdev)
6088{
Johan Hedberg890ea892013-03-15 17:06:52 -05006089 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006090 u8 link_sec;
6091
Johan Hedberg890ea892013-03-15 17:06:52 -05006092 hci_req_init(&req, hdev);
6093
Johan Hedberg70da6242013-03-15 17:06:51 -05006094 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) &&
6095 !lmp_host_ssp_capable(hdev)) {
6096 u8 ssp = 1;
6097
Johan Hedberg890ea892013-03-15 17:06:52 -05006098 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006099 }
6100
Johan Hedbergc73eee92013-04-19 18:35:21 +03006101 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
6102 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006103 struct hci_cp_write_le_host_supported cp;
6104
Marcel Holtmann32226e42014-07-24 20:04:16 +02006105 cp.le = 0x01;
6106 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006107
6108 /* Check first if we already have the right
6109 * host state (host features set)
6110 */
6111 if (cp.le != lmp_host_le_capable(hdev) ||
6112 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006113 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6114 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006115 }
6116
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006117 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006118 /* Make sure the controller has a good default for
6119 * advertising data. This also applies to the case
6120 * where BR/EDR was toggled during the AUTO_OFF phase.
6121 */
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006122 if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006123 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006124 update_scan_rsp_data(&req);
6125 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006126
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006127 if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
6128 enable_advertising(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006129 }
6130
Johan Hedberg70da6242013-03-15 17:06:51 -05006131 link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags);
6132 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006133 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6134 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006135
6136 if (lmp_bredr_capable(hdev)) {
Johan Hedberg432df052014-08-01 11:13:31 +03006137 write_fast_connectable(&req, false);
6138 hci_update_page_scan(hdev, &req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006139 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006140 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006141 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006142 }
6143
Johan Hedberg229ab392013-03-15 17:06:53 -05006144 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006145}
6146
Johan Hedberg744cf192011-11-08 20:40:14 +02006147int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006148{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006149 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg229ab392013-03-15 17:06:53 -05006150 u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
6151 u8 zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006152 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006153
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006154 if (!test_bit(HCI_MGMT, &hdev->dev_flags))
6155 return 0;
6156
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006157 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006158 if (powered_update_hci(hdev) == 0)
6159 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006160
Johan Hedberg229ab392013-03-15 17:06:53 -05006161 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6162 &match);
6163 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006164 }
6165
Johan Hedberg229ab392013-03-15 17:06:53 -05006166 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02006167 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status_not_powered);
Johan Hedberg229ab392013-03-15 17:06:53 -05006168
6169 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6170 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6171 zero_cod, sizeof(zero_cod), NULL);
6172
6173new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006174 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006175
6176 if (match.sk)
6177 sock_put(match.sk);
6178
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006179 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006180}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006181
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006182void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006183{
6184 struct pending_cmd *cmd;
6185 u8 status;
6186
6187 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6188 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006189 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006190
6191 if (err == -ERFKILL)
6192 status = MGMT_STATUS_RFKILLED;
6193 else
6194 status = MGMT_STATUS_FAILED;
6195
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006196 cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006197
6198 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006199}
6200
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006201void mgmt_discoverable_timeout(struct hci_dev *hdev)
6202{
6203 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006204
6205 hci_dev_lock(hdev);
6206
6207 /* When discoverable timeout triggers, then just make sure
6208 * the limited discoverable flag is cleared. Even in the case
6209 * of a timeout triggered from general discoverable, it is
6210 * safe to unconditionally clear the flag.
6211 */
6212 clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006213 clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006214
6215 hci_req_init(&req, hdev);
Johan Hedberg4b580612013-10-19 23:38:21 +03006216 if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
6217 u8 scan = SCAN_PAGE;
6218 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6219 sizeof(scan), &scan);
6220 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006221 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006222 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006223 hci_req_run(&req, NULL);
6224
6225 hdev->discov_timeout = 0;
6226
Johan Hedberg9a43e252013-10-20 19:00:07 +03006227 new_settings(hdev, NULL);
6228
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006229 hci_dev_unlock(hdev);
6230}
6231
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006232void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6233 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006234{
Johan Hedberg86742e12011-11-07 23:13:38 +02006235 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006236
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006237 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006238
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006239 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006240 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006241 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006242 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006243 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006244 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006245
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006246 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006247}
Johan Hedbergf7520542011-01-20 12:34:39 +02006248
Johan Hedbergd7b25452014-05-23 13:19:53 +03006249static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6250{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006251 switch (ltk->type) {
6252 case SMP_LTK:
6253 case SMP_LTK_SLAVE:
6254 if (ltk->authenticated)
6255 return MGMT_LTK_AUTHENTICATED;
6256 return MGMT_LTK_UNAUTHENTICATED;
6257 case SMP_LTK_P256:
6258 if (ltk->authenticated)
6259 return MGMT_LTK_P256_AUTH;
6260 return MGMT_LTK_P256_UNAUTH;
6261 case SMP_LTK_P256_DEBUG:
6262 return MGMT_LTK_P256_DEBUG;
6263 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006264
6265 return MGMT_LTK_UNAUTHENTICATED;
6266}
6267
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006268void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006269{
6270 struct mgmt_ev_new_long_term_key ev;
6271
6272 memset(&ev, 0, sizeof(ev));
6273
Marcel Holtmann5192d302014-02-19 17:11:58 -08006274 /* Devices using resolvable or non-resolvable random addresses
6275 * without providing an indentity resolving key don't require
6276 * to store long term keys. Their addresses will change the
6277 * next time around.
6278 *
6279 * Only when a remote device provides an identity address
6280 * make sure the long term key is stored. If the remote
6281 * identity is known, the long term keys are internally
6282 * mapped to the identity address. So allow static random
6283 * and public addresses here.
6284 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006285 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6286 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6287 ev.store_hint = 0x00;
6288 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006289 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006290
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006291 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006292 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006293 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006294 ev.key.enc_size = key->enc_size;
6295 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006296 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006297
Johan Hedberg2ceba532014-06-16 19:25:16 +03006298 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006299 ev.key.master = 1;
6300
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006301 memcpy(ev.key.val, key->val, sizeof(key->val));
6302
Marcel Holtmann083368f2013-10-15 14:26:29 -07006303 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006304}
6305
Johan Hedberg95fbac82014-02-19 15:18:31 +02006306void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6307{
6308 struct mgmt_ev_new_irk ev;
6309
6310 memset(&ev, 0, sizeof(ev));
6311
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006312 /* For identity resolving keys from devices that are already
6313 * using a public address or static random address, do not
6314 * ask for storing this key. The identity resolving key really
6315 * is only mandatory for devices using resovlable random
6316 * addresses.
6317 *
6318 * Storing all identity resolving keys has the downside that
6319 * they will be also loaded on next boot of they system. More
6320 * identity resolving keys, means more time during scanning is
6321 * needed to actually resolve these addresses.
6322 */
6323 if (bacmp(&irk->rpa, BDADDR_ANY))
6324 ev.store_hint = 0x01;
6325 else
6326 ev.store_hint = 0x00;
6327
Johan Hedberg95fbac82014-02-19 15:18:31 +02006328 bacpy(&ev.rpa, &irk->rpa);
6329 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6330 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6331 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6332
6333 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6334}
6335
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006336void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6337 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006338{
6339 struct mgmt_ev_new_csrk ev;
6340
6341 memset(&ev, 0, sizeof(ev));
6342
6343 /* Devices using resolvable or non-resolvable random addresses
6344 * without providing an indentity resolving key don't require
6345 * to store signature resolving keys. Their addresses will change
6346 * the next time around.
6347 *
6348 * Only when a remote device provides an identity address
6349 * make sure the signature resolving key is stored. So allow
6350 * static random and public addresses here.
6351 */
6352 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6353 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6354 ev.store_hint = 0x00;
6355 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006356 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006357
6358 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6359 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
6360 ev.key.master = csrk->master;
6361 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6362
6363 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6364}
6365
Andre Guedesffb5a8272014-07-01 18:10:11 -03006366void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006367 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6368 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006369{
6370 struct mgmt_ev_new_conn_param ev;
6371
Johan Hedbergc103aea2014-07-02 17:37:34 +03006372 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6373 return;
6374
Andre Guedesffb5a8272014-07-01 18:10:11 -03006375 memset(&ev, 0, sizeof(ev));
6376 bacpy(&ev.addr.bdaddr, bdaddr);
6377 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006378 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006379 ev.min_interval = cpu_to_le16(min_interval);
6380 ev.max_interval = cpu_to_le16(max_interval);
6381 ev.latency = cpu_to_le16(latency);
6382 ev.timeout = cpu_to_le16(timeout);
6383
6384 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6385}
6386
Marcel Holtmann94933992013-10-15 10:26:39 -07006387static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6388 u8 data_len)
6389{
6390 eir[eir_len++] = sizeof(type) + data_len;
6391 eir[eir_len++] = type;
6392 memcpy(&eir[eir_len], data, data_len);
6393 eir_len += data_len;
6394
6395 return eir_len;
6396}
6397
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006398void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6399 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006400{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006401 char buf[512];
6402 struct mgmt_ev_device_connected *ev = (void *) buf;
6403 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006404
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006405 bacpy(&ev->addr.bdaddr, &conn->dst);
6406 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006407
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006408 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006409
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006410 /* We must ensure that the EIR Data fields are ordered and
6411 * unique. Keep it simple for now and avoid the problem by not
6412 * adding any BR/EDR data to the LE adv.
6413 */
6414 if (conn->le_adv_data_len > 0) {
6415 memcpy(&ev->eir[eir_len],
6416 conn->le_adv_data, conn->le_adv_data_len);
6417 eir_len = conn->le_adv_data_len;
6418 } else {
6419 if (name_len > 0)
6420 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6421 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006422
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006423 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006424 eir_len = eir_append_data(ev->eir, eir_len,
6425 EIR_CLASS_OF_DEV,
6426 conn->dev_class, 3);
6427 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006428
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006429 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006430
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006431 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6432 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006433}
6434
Johan Hedberg8962ee72011-01-20 12:40:27 +02006435static void disconnect_rsp(struct pending_cmd *cmd, void *data)
6436{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006437 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006438
Johan Hedbergf5818c22014-12-05 13:36:02 +02006439 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006440
6441 *sk = cmd->sk;
6442 sock_hold(*sk);
6443
Johan Hedberga664b5b2011-02-19 12:06:02 -03006444 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006445}
6446
Johan Hedberg124f6e32012-02-09 13:50:12 +02006447static void unpair_device_rsp(struct pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006448{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006449 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006450 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006451
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006452 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6453
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006454 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006455 mgmt_pending_remove(cmd);
6456}
6457
Johan Hedberg84c61d92014-08-01 11:13:30 +03006458bool mgmt_powering_down(struct hci_dev *hdev)
6459{
6460 struct pending_cmd *cmd;
6461 struct mgmt_mode *cp;
6462
6463 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6464 if (!cmd)
6465 return false;
6466
6467 cp = cmd->param;
6468 if (!cp->val)
6469 return true;
6470
6471 return false;
6472}
6473
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006474void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006475 u8 link_type, u8 addr_type, u8 reason,
6476 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006477{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006478 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006479 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006480
Johan Hedberg84c61d92014-08-01 11:13:30 +03006481 /* The connection is still in hci_conn_hash so test for 1
6482 * instead of 0 to know if this is the last one.
6483 */
6484 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6485 cancel_delayed_work(&hdev->power_off);
6486 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006487 }
6488
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006489 if (!mgmt_connected)
6490 return;
6491
Andre Guedes57eb7762013-10-30 19:01:41 -03006492 if (link_type != ACL_LINK && link_type != LE_LINK)
6493 return;
6494
Johan Hedberg744cf192011-11-08 20:40:14 +02006495 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006496
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006497 bacpy(&ev.addr.bdaddr, bdaddr);
6498 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6499 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006500
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006501 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006502
6503 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006504 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006505
Johan Hedberg124f6e32012-02-09 13:50:12 +02006506 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006507 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006508}
6509
Marcel Holtmann78929242013-10-06 23:55:47 -07006510void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6511 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006512{
Andre Guedes3655bba2013-10-30 19:01:40 -03006513 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6514 struct mgmt_cp_disconnect *cp;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006515 struct pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006516
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006517 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6518 hdev);
6519
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006520 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006521 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006522 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006523
Andre Guedes3655bba2013-10-30 19:01:40 -03006524 cp = cmd->param;
6525
6526 if (bacmp(bdaddr, &cp->addr.bdaddr))
6527 return;
6528
6529 if (cp->addr.type != bdaddr_type)
6530 return;
6531
Johan Hedbergf5818c22014-12-05 13:36:02 +02006532 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006533 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006534}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006535
Marcel Holtmann445608d2013-10-06 23:55:48 -07006536void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6537 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006538{
6539 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006540
Johan Hedberg84c61d92014-08-01 11:13:30 +03006541 /* The connection is still in hci_conn_hash so test for 1
6542 * instead of 0 to know if this is the last one.
6543 */
6544 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6545 cancel_delayed_work(&hdev->power_off);
6546 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006547 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006548
Johan Hedberg4c659c32011-11-07 23:13:39 +02006549 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006550 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006551 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006552
Marcel Holtmann445608d2013-10-06 23:55:48 -07006553 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006554}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006555
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006556void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006557{
6558 struct mgmt_ev_pin_code_request ev;
6559
Johan Hedbergd8457692012-02-17 14:24:57 +02006560 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006561 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006562 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006563
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006564 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006565}
6566
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006567void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6568 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006569{
6570 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006571
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006572 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006573 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006574 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006575
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006576 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006577 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006578}
6579
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006580void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6581 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006582{
6583 struct pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006584
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006585 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006586 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006587 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006588
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006589 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006590 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006591}
Johan Hedberga5c29682011-02-19 12:05:57 -03006592
Johan Hedberg744cf192011-11-08 20:40:14 +02006593int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006594 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006595 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03006596{
6597 struct mgmt_ev_user_confirm_request ev;
6598
Johan Hedberg744cf192011-11-08 20:40:14 +02006599 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03006600
Johan Hedberg272d90d2012-02-09 15:26:12 +02006601 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006602 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07006603 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02006604 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03006605
Johan Hedberg744cf192011-11-08 20:40:14 +02006606 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006607 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03006608}
6609
Johan Hedberg272d90d2012-02-09 15:26:12 +02006610int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006611 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08006612{
6613 struct mgmt_ev_user_passkey_request ev;
6614
6615 BT_DBG("%s", hdev->name);
6616
Johan Hedberg272d90d2012-02-09 15:26:12 +02006617 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006618 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08006619
6620 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006621 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08006622}
6623
Brian Gix0df4c182011-11-16 13:53:13 -08006624static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03006625 u8 link_type, u8 addr_type, u8 status,
6626 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03006627{
6628 struct pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03006629
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006630 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03006631 if (!cmd)
6632 return -ENOENT;
6633
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006634 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006635 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03006636
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006637 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03006638}
6639
Johan Hedberg744cf192011-11-08 20:40:14 +02006640int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006641 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006642{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006643 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006644 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006645}
6646
Johan Hedberg272d90d2012-02-09 15:26:12 +02006647int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006648 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03006649{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006650 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006651 status,
6652 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03006653}
Johan Hedberg2a611692011-02-19 12:06:00 -03006654
Brian Gix604086b2011-11-23 08:28:33 -08006655int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006656 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006657{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006658 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006659 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006660}
6661
Johan Hedberg272d90d2012-02-09 15:26:12 +02006662int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006663 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08006664{
Johan Hedberg272d90d2012-02-09 15:26:12 +02006665 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03006666 status,
6667 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08006668}
6669
Johan Hedberg92a25252012-09-06 18:39:26 +03006670int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
6671 u8 link_type, u8 addr_type, u32 passkey,
6672 u8 entered)
6673{
6674 struct mgmt_ev_passkey_notify ev;
6675
6676 BT_DBG("%s", hdev->name);
6677
6678 bacpy(&ev.addr.bdaddr, bdaddr);
6679 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6680 ev.passkey = __cpu_to_le32(passkey);
6681 ev.entered = entered;
6682
6683 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
6684}
6685
Johan Hedberge1e930f2014-09-08 17:09:49 -07006686void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03006687{
6688 struct mgmt_ev_auth_failed ev;
Johan Hedberge1e930f2014-09-08 17:09:49 -07006689 struct pending_cmd *cmd;
6690 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006691
Johan Hedberge1e930f2014-09-08 17:09:49 -07006692 bacpy(&ev.addr.bdaddr, &conn->dst);
6693 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
6694 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03006695
Johan Hedberge1e930f2014-09-08 17:09:49 -07006696 cmd = find_pairing(conn);
6697
6698 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
6699 cmd ? cmd->sk : NULL);
6700
6701 if (cmd)
6702 pairing_complete(cmd, status);
Johan Hedberg2a611692011-02-19 12:06:00 -03006703}
Johan Hedbergb312b1612011-03-16 14:29:37 +02006704
Marcel Holtmann464996a2013-10-15 14:26:24 -07006705void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006706{
6707 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07006708 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006709
6710 if (status) {
6711 u8 mgmt_err = mgmt_status(status);
6712 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006713 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07006714 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006715 }
6716
Marcel Holtmann464996a2013-10-15 14:26:24 -07006717 if (test_bit(HCI_AUTH, &hdev->flags))
6718 changed = !test_and_set_bit(HCI_LINK_SECURITY,
6719 &hdev->dev_flags);
6720 else
6721 changed = test_and_clear_bit(HCI_LINK_SECURITY,
6722 &hdev->dev_flags);
Johan Hedberg47990ea2012-02-22 11:58:37 +02006723
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006724 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006725 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006726
Johan Hedberg47990ea2012-02-22 11:58:37 +02006727 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07006728 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006729
6730 if (match.sk)
6731 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02006732}
6733
Johan Hedberg890ea892013-03-15 17:06:52 -05006734static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02006735{
Johan Hedberg890ea892013-03-15 17:06:52 -05006736 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006737 struct hci_cp_write_eir cp;
6738
Johan Hedberg976eb202012-10-24 21:12:01 +03006739 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006740 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02006741
Johan Hedbergc80da272012-02-22 15:38:48 +02006742 memset(hdev->eir, 0, sizeof(hdev->eir));
6743
Johan Hedbergcacaf522012-02-21 00:52:42 +02006744 memset(&cp, 0, sizeof(cp));
6745
Johan Hedberg890ea892013-03-15 17:06:52 -05006746 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02006747}
6748
Marcel Holtmann3e248562013-10-15 14:26:25 -07006749void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006750{
6751 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05006752 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006753 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006754
6755 if (status) {
6756 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006757
6758 if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006759 &hdev->dev_flags)) {
6760 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006761 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006762 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006763
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006764 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
6765 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07006766 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006767 }
6768
6769 if (enable) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006770 changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006771 } else {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07006772 changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
6773 if (!changed)
6774 changed = test_and_clear_bit(HCI_HS_ENABLED,
6775 &hdev->dev_flags);
6776 else
6777 clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006778 }
6779
6780 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
6781
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02006782 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07006783 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006784
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02006785 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006786 sock_put(match.sk);
6787
Johan Hedberg890ea892013-03-15 17:06:52 -05006788 hci_req_init(&req, hdev);
6789
Johan Hedberg37699722014-06-24 14:00:27 +03006790 if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
6791 if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags))
6792 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
6793 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05006794 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006795 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05006796 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03006797 }
Johan Hedberg890ea892013-03-15 17:06:52 -05006798
6799 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02006800}
6801
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006802void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
6803{
6804 struct cmd_lookup match = { NULL, hdev };
6805 bool changed = false;
6806
6807 if (status) {
6808 u8 mgmt_err = mgmt_status(status);
6809
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006810 if (enable) {
6811 if (test_and_clear_bit(HCI_SC_ENABLED,
6812 &hdev->dev_flags))
6813 new_settings(hdev, NULL);
6814 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6815 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006816
6817 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6818 cmd_status_rsp, &mgmt_err);
6819 return;
6820 }
6821
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006822 if (enable) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006823 changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006824 } else {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006825 changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08006826 clear_bit(HCI_SC_ONLY, &hdev->dev_flags);
6827 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08006828
6829 mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev,
6830 settings_rsp, &match);
6831
6832 if (changed)
6833 new_settings(hdev, match.sk);
6834
6835 if (match.sk)
6836 sock_put(match.sk);
6837}
6838
Johan Hedberg92da6092013-03-15 17:06:55 -05006839static void sk_lookup(struct pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02006840{
6841 struct cmd_lookup *match = data;
6842
Johan Hedberg90e70452012-02-23 23:09:40 +02006843 if (match->sk == NULL) {
6844 match->sk = cmd->sk;
6845 sock_hold(match->sk);
6846 }
Johan Hedberg90e70452012-02-23 23:09:40 +02006847}
6848
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006849void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
6850 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006851{
Johan Hedberg90e70452012-02-23 23:09:40 +02006852 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006853
Johan Hedberg92da6092013-03-15 17:06:55 -05006854 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
6855 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
6856 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02006857
6858 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07006859 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
6860 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02006861
6862 if (match.sk)
6863 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01006864}
6865
Marcel Holtmann7667da32013-10-15 14:26:27 -07006866void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02006867{
Johan Hedbergb312b1612011-03-16 14:29:37 +02006868 struct mgmt_cp_set_local_name ev;
Johan Hedberg13928972013-03-15 17:07:00 -05006869 struct pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006870
Johan Hedberg13928972013-03-15 17:07:00 -05006871 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07006872 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006873
6874 memset(&ev, 0, sizeof(ev));
6875 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02006876 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006877
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006878 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05006879 if (!cmd) {
6880 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02006881
Johan Hedberg13928972013-03-15 17:07:00 -05006882 /* If this is a HCI command related to powering on the
6883 * HCI dev don't send any mgmt signals.
6884 */
6885 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07006886 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02006887 }
6888
Marcel Holtmann7667da32013-10-15 14:26:27 -07006889 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
6890 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02006891}
Szymon Jancc35938b2011-03-22 13:12:21 +01006892
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006893void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02006894 u8 *rand192, u8 *hash256, u8 *rand256,
6895 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01006896{
6897 struct pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01006898
Johan Hedberg744cf192011-11-08 20:40:14 +02006899 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01006900
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006901 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01006902 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006903 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01006904
6905 if (status) {
Marcel Holtmann3edaf092013-10-15 14:26:28 -07006906 cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
6907 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01006908 } else {
Johan Hedberg710f11c2014-05-26 11:21:22 +03006909 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006910 struct mgmt_rp_read_local_oob_ext_data rp;
Szymon Jancc35938b2011-03-22 13:12:21 +01006911
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006912 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
Johan Hedberg38da1702014-11-17 20:52:20 +02006913 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
Szymon Jancc35938b2011-03-22 13:12:21 +01006914
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006915 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02006916 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006917
6918 cmd_complete(cmd->sk, hdev->id,
6919 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6920 &rp, sizeof(rp));
6921 } else {
6922 struct mgmt_rp_read_local_oob_data rp;
6923
6924 memcpy(rp.hash, hash192, sizeof(rp.hash));
Johan Hedberg38da1702014-11-17 20:52:20 +02006925 memcpy(rp.rand, rand192, sizeof(rp.rand));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08006926
6927 cmd_complete(cmd->sk, hdev->id,
6928 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
6929 &rp, sizeof(rp));
6930 }
Szymon Jancc35938b2011-03-22 13:12:21 +01006931 }
6932
6933 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01006934}
Johan Hedberge17acd42011-03-30 23:57:16 +03006935
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006936/* this is reversed hex representation of bluetooth base uuid. We need it for
6937 * service uuid parsing in eir.
6938 */
6939static const u8 reverse_base_uuid[] = {
6940 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
6941 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
6942};
6943
6944static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
6945{
6946 int i;
6947
6948 for (i = 0; i < uuid_count; i++) {
6949 if (!memcmp(uuid, uuids[i], 16))
6950 return true;
6951 }
6952
6953 return false;
6954}
6955
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01006956static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
6957{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01006958 u16 parsed = 0;
6959
6960 while (parsed < eir_len) {
6961 u8 field_len = eir[0];
6962 u8 uuid[16];
6963 int i;
6964
6965 if (field_len == 0)
6966 break;
6967
6968 if (eir_len - parsed < field_len + 1)
6969 break;
6970
6971 switch (eir[1]) {
6972 case EIR_UUID16_ALL:
6973 case EIR_UUID16_SOME:
6974 for (i = 0; i + 3 <= field_len; i += 2) {
6975 memcpy(uuid, reverse_base_uuid, 16);
6976 uuid[13] = eir[i + 3];
6977 uuid[12] = eir[i + 2];
6978 if (has_uuid(uuid, uuid_count, uuids))
6979 return true;
6980 }
6981 break;
6982 case EIR_UUID32_ALL:
6983 case EIR_UUID32_SOME:
6984 for (i = 0; i + 5 <= field_len; i += 4) {
6985 memcpy(uuid, reverse_base_uuid, 16);
6986 uuid[15] = eir[i + 5];
6987 uuid[14] = eir[i + 4];
6988 uuid[13] = eir[i + 3];
6989 uuid[12] = eir[i + 2];
6990 if (has_uuid(uuid, uuid_count, uuids))
6991 return true;
6992 }
6993 break;
6994 case EIR_UUID128_ALL:
6995 case EIR_UUID128_SOME:
6996 for (i = 0; i + 17 <= field_len; i += 16) {
6997 memcpy(uuid, eir + i + 2, 16);
6998 if (has_uuid(uuid, uuid_count, uuids))
6999 return true;
7000 }
7001 break;
7002 }
7003
7004 parsed += field_len + 1;
7005 eir += field_len + 1;
7006 }
7007
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007008 return false;
7009}
7010
Marcel Holtmann901801b2013-10-06 23:55:51 -07007011void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007012 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7013 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007014{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007015 char buf[512];
7016 struct mgmt_ev_device_found *ev = (void *) buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007017 size_t ev_size;
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007018 bool match;
Johan Hedberge17acd42011-03-30 23:57:16 +03007019
Johan Hedberg75ce2082014-07-02 22:42:01 +03007020 /* Don't send events for a non-kernel initiated discovery. With
7021 * LE one exception is if we have pend_le_reports > 0 in which
7022 * case we're doing passive scanning and want these events.
7023 */
7024 if (!hci_discovery_active(hdev)) {
7025 if (link_type == ACL_LINK)
7026 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007027 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007028 return;
7029 }
Andre Guedes12602d02013-04-30 15:29:40 -03007030
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007031 /* When using service discovery with a RSSI threshold, then check
7032 * if such a RSSI threshold is specified. If a RSSI threshold has
7033 * been specified, then all results with a RSSI smaller than the
7034 * RSSI threshold will be dropped.
7035 */
7036 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7037 rssi < hdev->discovery.rssi)
7038 return;
7039
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007040 /* Make sure that the buffer is big enough. The 5 extra bytes
7041 * are for the potential CoD field.
7042 */
7043 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007044 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007045
Johan Hedberg1dc06092012-01-15 21:01:23 +02007046 memset(buf, 0, sizeof(buf));
7047
Johan Hedberg841c5642014-07-07 12:45:54 +03007048 bacpy(&ev->addr.bdaddr, bdaddr);
7049 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007050 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007051 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007052
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007053 if (eir_len > 0) {
7054 /* When using service discovery and a list of UUID is
7055 * provided, results with no matching UUID should be
7056 * dropped. In case there is a match the result is
7057 * kept and checking possible scan response data
7058 * will be skipped.
7059 */
7060 if (hdev->discovery.uuid_count > 0) {
7061 match = eir_has_uuids(eir, eir_len,
7062 hdev->discovery.uuid_count,
7063 hdev->discovery.uuids);
7064 if (!match)
7065 return;
7066 }
7067
7068 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007069 memcpy(ev->eir, eir, eir_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007070 } else {
7071 /* When using service discovery and a list of UUID is
7072 * provided, results with empty EIR or advertising data
7073 * should be dropped since they do not match any UUID.
7074 */
7075 if (hdev->discovery.uuid_count > 0)
7076 return;
7077 }
Johan Hedberge17acd42011-03-30 23:57:16 +03007078
Johan Hedberg1dc06092012-01-15 21:01:23 +02007079 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7080 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007081 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007082
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007083 if (scan_rsp_len > 0) {
7084 /* When using service discovery and a list of UUID is
7085 * provided, results with no matching UUID should be
7086 * dropped if there is no previous match from the
7087 * advertising data.
7088 */
7089 if (hdev->discovery.uuid_count > 0) {
7090 if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
7091 hdev->discovery.uuid_count,
7092 hdev->discovery.uuids))
7093 return;
7094 }
7095
7096 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007097 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007098 } else {
7099 /* When using service discovery and a list of UUID is
7100 * provided, results with empty scan response and no
7101 * previous matched advertising data should be dropped.
7102 */
7103 if (hdev->discovery.uuid_count > 0 && !match)
7104 return;
7105 }
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007106
7107 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7108 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007109
Marcel Holtmann901801b2013-10-06 23:55:51 -07007110 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007111}
Johan Hedberga88a9652011-03-30 13:18:12 +03007112
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007113void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7114 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007115{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007116 struct mgmt_ev_device_found *ev;
7117 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7118 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007119
Johan Hedbergb644ba32012-01-17 21:48:47 +02007120 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007121
Johan Hedbergb644ba32012-01-17 21:48:47 +02007122 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007123
Johan Hedbergb644ba32012-01-17 21:48:47 +02007124 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007125 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007126 ev->rssi = rssi;
7127
7128 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007129 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007130
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007131 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007132
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007133 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007134}
Johan Hedberg314b2382011-04-27 10:29:57 -04007135
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007136void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007137{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007138 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007139
Andre Guedes343fb142011-11-22 17:14:19 -03007140 BT_DBG("%s discovering %u", hdev->name, discovering);
7141
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007142 memset(&ev, 0, sizeof(ev));
7143 ev.type = hdev->discovery.type;
7144 ev.discovering = discovering;
7145
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007146 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007147}
Antti Julku5e762442011-08-25 16:48:02 +03007148
Marcel Holtmann5976e602013-10-06 04:08:14 -07007149static void adv_enable_complete(struct hci_dev *hdev, u8 status)
7150{
7151 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007152}
7153
7154void mgmt_reenable_advertising(struct hci_dev *hdev)
7155{
7156 struct hci_request req;
7157
Marcel Holtmann5976e602013-10-06 04:08:14 -07007158 if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags))
7159 return;
7160
7161 hci_req_init(&req, hdev);
7162 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007163 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007164}