blob: 56f49e9c4189d01836d4d157bffba8da4517a5d6 [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 Hedberg71290692015-02-20 13:26:23 +020032#include <net/bluetooth/hci_sock.h>
Johan Hedberg4bc58f52014-05-20 09:45:47 +030033#include <net/bluetooth/l2cap.h>
Johan Hedberg03811012010-12-08 00:21:06 +020034#include <net/bluetooth/mgmt.h>
Marcel Holtmannac4b7232013-10-10 14:54:16 -070035
Johan Hedberg0857dd32014-12-19 13:40:20 +020036#include "hci_request.h"
Marcel Holtmannac4b7232013-10-10 14:54:16 -070037#include "smp.h"
Johan Hedberg03811012010-12-08 00:21:06 +020038
Johan Hedberg2da9c552012-02-17 14:39:28 +020039#define MGMT_VERSION 1
Marcel Holtmannbeb1c212015-03-10 14:04:52 -070040#define MGMT_REVISION 9
Johan Hedberg02d98122010-12-13 21:07:04 +020041
Johan Hedberge70bb2e2012-02-13 16:59:33 +020042static const u16 mgmt_commands[] = {
43 MGMT_OP_READ_INDEX_LIST,
44 MGMT_OP_READ_INFO,
45 MGMT_OP_SET_POWERED,
46 MGMT_OP_SET_DISCOVERABLE,
47 MGMT_OP_SET_CONNECTABLE,
48 MGMT_OP_SET_FAST_CONNECTABLE,
Johan Hedbergb2939472014-07-30 09:22:23 +030049 MGMT_OP_SET_BONDABLE,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020050 MGMT_OP_SET_LINK_SECURITY,
51 MGMT_OP_SET_SSP,
52 MGMT_OP_SET_HS,
53 MGMT_OP_SET_LE,
54 MGMT_OP_SET_DEV_CLASS,
55 MGMT_OP_SET_LOCAL_NAME,
56 MGMT_OP_ADD_UUID,
57 MGMT_OP_REMOVE_UUID,
58 MGMT_OP_LOAD_LINK_KEYS,
59 MGMT_OP_LOAD_LONG_TERM_KEYS,
60 MGMT_OP_DISCONNECT,
61 MGMT_OP_GET_CONNECTIONS,
62 MGMT_OP_PIN_CODE_REPLY,
63 MGMT_OP_PIN_CODE_NEG_REPLY,
64 MGMT_OP_SET_IO_CAPABILITY,
65 MGMT_OP_PAIR_DEVICE,
66 MGMT_OP_CANCEL_PAIR_DEVICE,
67 MGMT_OP_UNPAIR_DEVICE,
68 MGMT_OP_USER_CONFIRM_REPLY,
69 MGMT_OP_USER_CONFIRM_NEG_REPLY,
70 MGMT_OP_USER_PASSKEY_REPLY,
71 MGMT_OP_USER_PASSKEY_NEG_REPLY,
72 MGMT_OP_READ_LOCAL_OOB_DATA,
73 MGMT_OP_ADD_REMOTE_OOB_DATA,
74 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
75 MGMT_OP_START_DISCOVERY,
76 MGMT_OP_STOP_DISCOVERY,
77 MGMT_OP_CONFIRM_NAME,
78 MGMT_OP_BLOCK_DEVICE,
79 MGMT_OP_UNBLOCK_DEVICE,
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -070080 MGMT_OP_SET_DEVICE_ID,
Johan Hedberg4375f102013-09-25 13:26:10 +030081 MGMT_OP_SET_ADVERTISING,
Johan Hedberg0663ca22013-10-02 13:43:14 +030082 MGMT_OP_SET_BREDR,
Marcel Holtmannd13eafc2013-10-02 04:41:30 -070083 MGMT_OP_SET_STATIC_ADDRESS,
Marcel Holtmann7f72134e2013-10-11 14:44:58 -070084 MGMT_OP_SET_SCAN_PARAMS,
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -080085 MGMT_OP_SET_SECURE_CONN,
Marcel Holtmann4e39ac82014-01-31 11:55:22 -080086 MGMT_OP_SET_DEBUG_KEYS,
Johan Hedberg62b04cd2014-02-23 19:42:27 +020087 MGMT_OP_SET_PRIVACY,
Johan Hedberg41edf162014-02-18 10:19:35 +020088 MGMT_OP_LOAD_IRKS,
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +020089 MGMT_OP_GET_CONN_INFO,
Johan Hedberg95868422014-06-28 17:54:07 +030090 MGMT_OP_GET_CLOCK_INFO,
Marcel Holtmann2faade52014-06-29 19:44:03 +020091 MGMT_OP_ADD_DEVICE,
92 MGMT_OP_REMOVE_DEVICE,
Johan Hedberga26f3dc2014-07-02 17:37:29 +030093 MGMT_OP_LOAD_CONN_PARAM,
Marcel Holtmann73d1df22014-07-02 22:10:52 +020094 MGMT_OP_READ_UNCONF_INDEX_LIST,
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +020095 MGMT_OP_READ_CONFIG_INFO,
Marcel Holtmanndbece372014-07-04 18:11:55 +020096 MGMT_OP_SET_EXTERNAL_CONFIG,
Marcel Holtmann9713c172014-07-06 12:11:15 +020097 MGMT_OP_SET_PUBLIC_ADDRESS,
Jakub Pawlowski66ea9422014-12-05 10:55:59 +010098 MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberge70bb2e2012-02-13 16:59:33 +020099};
100
101static const u16 mgmt_events[] = {
102 MGMT_EV_CONTROLLER_ERROR,
103 MGMT_EV_INDEX_ADDED,
104 MGMT_EV_INDEX_REMOVED,
105 MGMT_EV_NEW_SETTINGS,
106 MGMT_EV_CLASS_OF_DEV_CHANGED,
107 MGMT_EV_LOCAL_NAME_CHANGED,
108 MGMT_EV_NEW_LINK_KEY,
109 MGMT_EV_NEW_LONG_TERM_KEY,
110 MGMT_EV_DEVICE_CONNECTED,
111 MGMT_EV_DEVICE_DISCONNECTED,
112 MGMT_EV_CONNECT_FAILED,
113 MGMT_EV_PIN_CODE_REQUEST,
114 MGMT_EV_USER_CONFIRM_REQUEST,
115 MGMT_EV_USER_PASSKEY_REQUEST,
116 MGMT_EV_AUTH_FAILED,
117 MGMT_EV_DEVICE_FOUND,
118 MGMT_EV_DISCOVERING,
119 MGMT_EV_DEVICE_BLOCKED,
120 MGMT_EV_DEVICE_UNBLOCKED,
121 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300122 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800123 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700124 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200125 MGMT_EV_DEVICE_ADDED,
126 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300127 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200128 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200129 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200130 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700131 MGMT_EV_EXT_INDEX_ADDED,
132 MGMT_EV_EXT_INDEX_REMOVED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200133};
134
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800135#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200136
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200137#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
138 "\x00\x00\x00\x00\x00\x00\x00\x00"
139
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200140struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200142 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200143 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100144 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200145 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200146 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300147 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200148 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200149};
150
Johan Hedbergca69b792011-11-11 18:10:00 +0200151/* HCI to MGMT error code conversion table */
152static u8 mgmt_status_table[] = {
153 MGMT_STATUS_SUCCESS,
154 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
155 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
156 MGMT_STATUS_FAILED, /* Hardware Failure */
157 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
158 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200159 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200160 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
161 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
162 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
163 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
164 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
165 MGMT_STATUS_BUSY, /* Command Disallowed */
166 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
167 MGMT_STATUS_REJECTED, /* Rejected Security */
168 MGMT_STATUS_REJECTED, /* Rejected Personal */
169 MGMT_STATUS_TIMEOUT, /* Host Timeout */
170 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
171 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
172 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
173 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
174 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
175 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
176 MGMT_STATUS_BUSY, /* Repeated Attempts */
177 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
178 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
179 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
180 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
181 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
182 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
183 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
184 MGMT_STATUS_FAILED, /* Unspecified Error */
185 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
186 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
187 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
188 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
189 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
190 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
191 MGMT_STATUS_FAILED, /* Unit Link Key Used */
192 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
193 MGMT_STATUS_TIMEOUT, /* Instant Passed */
194 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
195 MGMT_STATUS_FAILED, /* Transaction Collision */
196 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
197 MGMT_STATUS_REJECTED, /* QoS Rejected */
198 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
199 MGMT_STATUS_REJECTED, /* Insufficient Security */
200 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
201 MGMT_STATUS_BUSY, /* Role Switch Pending */
202 MGMT_STATUS_FAILED, /* Slot Violation */
203 MGMT_STATUS_FAILED, /* Role Switch Failed */
204 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
205 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
206 MGMT_STATUS_BUSY, /* Host Busy Pairing */
207 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
208 MGMT_STATUS_BUSY, /* Controller Busy */
209 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
210 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
211 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
212 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
213 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
214};
215
216static u8 mgmt_status(u8 hci_status)
217{
218 if (hci_status < ARRAY_SIZE(mgmt_status_table))
219 return mgmt_status_table[hci_status];
220
221 return MGMT_STATUS_FAILED;
222}
223
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200224static int mgmt_send_event(u16 event, struct hci_dev *hdev,
225 unsigned short channel, void *data, u16 data_len,
226 struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200227{
228 struct sk_buff *skb;
229 struct mgmt_hdr *hdr;
230
231 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
232 if (!skb)
233 return -ENOMEM;
234
235 hdr = (void *) skb_put(skb, sizeof(*hdr));
236 hdr->opcode = cpu_to_le16(event);
237 if (hdev)
238 hdr->index = cpu_to_le16(hdev->id);
239 else
240 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
241 hdr->len = cpu_to_le16(data_len);
242
243 if (data)
244 memcpy(skb_put(skb, data_len), data, data_len);
245
246 /* Time stamp */
247 __net_timestamp(skb);
248
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200249 hci_send_to_channel(channel, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200250 kfree_skb(skb);
251
252 return 0;
253}
254
Marcel Holtmannf9207332015-03-14 19:27:55 -0700255static int mgmt_index_event(u16 event, struct hci_dev *hdev,
256 void *data, u16 data_len, int flag)
257{
258 struct sk_buff *skb;
259 struct mgmt_hdr *hdr;
260
261 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
262 if (!skb)
263 return -ENOMEM;
264
265 hdr = (void *) skb_put(skb, sizeof(*hdr));
266 hdr->opcode = cpu_to_le16(event);
267 hdr->index = cpu_to_le16(hdev->id);
268 hdr->len = cpu_to_le16(data_len);
269
270 if (data)
271 memcpy(skb_put(skb, data_len), data, data_len);
272
273 /* Time stamp */
274 __net_timestamp(skb);
275
276 hci_send_to_flagged_channel(HCI_CHANNEL_CONTROL, skb, flag);
277 kfree_skb(skb);
278
279 return 0;
280}
281
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200282static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
283 struct sock *skip_sk)
284{
285 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
286 skip_sk);
287}
288
Johan Hedberga69e8372015-03-06 21:08:53 +0200289static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200290{
291 struct sk_buff *skb;
292 struct mgmt_hdr *hdr;
293 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300294 int err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200295
Szymon Janc34eb5252011-02-28 14:10:08 +0100296 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200297
Andre Guedes790eff42012-06-07 19:05:46 -0300298 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200299 if (!skb)
300 return -ENOMEM;
301
302 hdr = (void *) skb_put(skb, sizeof(*hdr));
303
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700304 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100305 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200306 hdr->len = cpu_to_le16(sizeof(*ev));
307
308 ev = (void *) skb_put(skb, sizeof(*ev));
309 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200310 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200311
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300312 err = sock_queue_rcv_skb(sk, skb);
313 if (err < 0)
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200314 kfree_skb(skb);
315
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300316 return err;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200317}
318
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200319static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
320 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200321{
322 struct sk_buff *skb;
323 struct mgmt_hdr *hdr;
324 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300325 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200326
327 BT_DBG("sock %p", sk);
328
Andre Guedes790eff42012-06-07 19:05:46 -0300329 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200330 if (!skb)
331 return -ENOMEM;
332
333 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200334
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700335 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100336 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200337 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200338
Johan Hedberga38528f2011-01-22 06:46:43 +0200339 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200340 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b2182012-02-18 15:07:59 +0200341 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100342
343 if (rp)
344 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200345
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300346 err = sock_queue_rcv_skb(sk, skb);
347 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200348 kfree_skb(skb);
349
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100350 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200351}
352
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300353static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
354 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200355{
356 struct mgmt_rp_read_version rp;
357
358 BT_DBG("sock %p", sk);
359
360 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700361 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200362
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200363 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
364 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200365}
366
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300367static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
368 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200369{
370 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200371 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
372 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200373 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200374 size_t rp_size;
375 int i, err;
376
377 BT_DBG("sock %p", sk);
378
379 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
380
381 rp = kmalloc(rp_size, GFP_KERNEL);
382 if (!rp)
383 return -ENOMEM;
384
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700385 rp->num_commands = cpu_to_le16(num_commands);
386 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200387
388 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
389 put_unaligned_le16(mgmt_commands[i], opcode);
390
391 for (i = 0; i < num_events; i++, opcode++)
392 put_unaligned_le16(mgmt_events[i], opcode);
393
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200394 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
395 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200396 kfree(rp);
397
398 return err;
399}
400
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300401static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
402 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200403{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200404 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200405 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200406 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200407 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300408 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200409
410 BT_DBG("sock %p", sk);
411
412 read_lock(&hci_dev_list_lock);
413
414 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300415 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200416 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700417 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700418 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200419 }
420
Johan Hedberga38528f2011-01-22 06:46:43 +0200421 rp_len = sizeof(*rp) + (2 * count);
422 rp = kmalloc(rp_len, GFP_ATOMIC);
423 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100424 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200425 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100426 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200427
Johan Hedberg476e44c2012-10-19 20:10:46 +0300428 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200429 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700430 if (hci_dev_test_flag(d, HCI_SETUP) ||
431 hci_dev_test_flag(d, HCI_CONFIG) ||
432 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200433 continue;
434
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200435 /* Devices marked as raw-only are neither configured
436 * nor unconfigured controllers.
437 */
438 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700439 continue;
440
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200441 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700442 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700443 rp->index[count++] = cpu_to_le16(d->id);
444 BT_DBG("Added hci%u", d->id);
445 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200446 }
447
Johan Hedberg476e44c2012-10-19 20:10:46 +0300448 rp->num_controllers = cpu_to_le16(count);
449 rp_len = sizeof(*rp) + (2 * count);
450
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200451 read_unlock(&hci_dev_list_lock);
452
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200453 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
454 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200455
Johan Hedberga38528f2011-01-22 06:46:43 +0200456 kfree(rp);
457
458 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200459}
460
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200461static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
462 void *data, u16 data_len)
463{
464 struct mgmt_rp_read_unconf_index_list *rp;
465 struct hci_dev *d;
466 size_t rp_len;
467 u16 count;
468 int err;
469
470 BT_DBG("sock %p", sk);
471
472 read_lock(&hci_dev_list_lock);
473
474 count = 0;
475 list_for_each_entry(d, &hci_dev_list, list) {
476 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700477 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200478 count++;
479 }
480
481 rp_len = sizeof(*rp) + (2 * count);
482 rp = kmalloc(rp_len, GFP_ATOMIC);
483 if (!rp) {
484 read_unlock(&hci_dev_list_lock);
485 return -ENOMEM;
486 }
487
488 count = 0;
489 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700490 if (hci_dev_test_flag(d, HCI_SETUP) ||
491 hci_dev_test_flag(d, HCI_CONFIG) ||
492 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200493 continue;
494
495 /* Devices marked as raw-only are neither configured
496 * nor unconfigured controllers.
497 */
498 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
499 continue;
500
501 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700502 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200503 rp->index[count++] = cpu_to_le16(d->id);
504 BT_DBG("Added hci%u", d->id);
505 }
506 }
507
508 rp->num_controllers = cpu_to_le16(count);
509 rp_len = sizeof(*rp) + (2 * count);
510
511 read_unlock(&hci_dev_list_lock);
512
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200513 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
514 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200515
516 kfree(rp);
517
518 return err;
519}
520
Marcel Holtmanndbece372014-07-04 18:11:55 +0200521static bool is_configured(struct hci_dev *hdev)
522{
523 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700524 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200525 return false;
526
527 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
528 !bacmp(&hdev->public_addr, BDADDR_ANY))
529 return false;
530
531 return true;
532}
533
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200534static __le32 get_missing_options(struct hci_dev *hdev)
535{
536 u32 options = 0;
537
Marcel Holtmanndbece372014-07-04 18:11:55 +0200538 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700539 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200540 options |= MGMT_OPTION_EXTERNAL_CONFIG;
541
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200542 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
543 !bacmp(&hdev->public_addr, BDADDR_ANY))
544 options |= MGMT_OPTION_PUBLIC_ADDRESS;
545
546 return cpu_to_le32(options);
547}
548
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200549static int new_options(struct hci_dev *hdev, struct sock *skip)
550{
551 __le32 options = get_missing_options(hdev);
552
553 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
554 sizeof(options), skip);
555}
556
Marcel Holtmanndbece372014-07-04 18:11:55 +0200557static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
558{
559 __le32 options = get_missing_options(hdev);
560
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200561 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
562 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200563}
564
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200565static int read_config_info(struct sock *sk, struct hci_dev *hdev,
566 void *data, u16 data_len)
567{
568 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200569 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200570
571 BT_DBG("sock %p %s", sk, hdev->name);
572
573 hci_dev_lock(hdev);
574
575 memset(&rp, 0, sizeof(rp));
576 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200577
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200578 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
579 options |= MGMT_OPTION_EXTERNAL_CONFIG;
580
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200581 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200582 options |= MGMT_OPTION_PUBLIC_ADDRESS;
583
584 rp.supported_options = cpu_to_le32(options);
585 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200586
587 hci_dev_unlock(hdev);
588
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200589 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
590 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200591}
592
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200593static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200594{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200595 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200596
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200597 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300598 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800599 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300600 settings |= MGMT_SETTING_CONNECTABLE;
601 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200602
Andre Guedesed3fa312012-07-24 15:03:46 -0300603 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500604 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
605 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200606 settings |= MGMT_SETTING_BREDR;
607 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700608
609 if (lmp_ssp_capable(hdev)) {
610 settings |= MGMT_SETTING_SSP;
611 settings |= MGMT_SETTING_HS;
612 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800613
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800614 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800615 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700616 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100617
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300618 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200619 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300620 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300621 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200622 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800623 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300624 }
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200625
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200626 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
627 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200628 settings |= MGMT_SETTING_CONFIGURATION;
629
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200630 return settings;
631}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200632
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200633static u32 get_current_settings(struct hci_dev *hdev)
634{
635 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200636
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200637 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100638 settings |= MGMT_SETTING_POWERED;
639
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700640 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200641 settings |= MGMT_SETTING_CONNECTABLE;
642
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700643 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500644 settings |= MGMT_SETTING_FAST_CONNECTABLE;
645
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700646 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200647 settings |= MGMT_SETTING_DISCOVERABLE;
648
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700649 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300650 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200651
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700652 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200653 settings |= MGMT_SETTING_BREDR;
654
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700655 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200656 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200657
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700658 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200659 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200660
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700661 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200662 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e62010-12-13 21:07:06 +0200663
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700664 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200665 settings |= MGMT_SETTING_HS;
666
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700667 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300668 settings |= MGMT_SETTING_ADVERTISING;
669
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700670 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800671 settings |= MGMT_SETTING_SECURE_CONN;
672
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700673 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800674 settings |= MGMT_SETTING_DEBUG_KEYS;
675
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700676 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200677 settings |= MGMT_SETTING_PRIVACY;
678
Marcel Holtmann93690c22015-03-06 10:11:21 -0800679 /* The current setting for static address has two purposes. The
680 * first is to indicate if the static address will be used and
681 * the second is to indicate if it is actually set.
682 *
683 * This means if the static address is not configured, this flag
684 * will never bet set. If the address is configured, then if the
685 * address is actually used decides if the flag is set or not.
686 *
687 * For single mode LE only controllers and dual-mode controllers
688 * with BR/EDR disabled, the existence of the static address will
689 * be evaluated.
690 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700691 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700692 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800693 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
694 if (bacmp(&hdev->static_addr, BDADDR_ANY))
695 settings |= MGMT_SETTING_STATIC_ADDRESS;
696 }
697
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200698 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200699}
700
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300701#define PNP_INFO_SVCLASS_ID 0x1200
702
Johan Hedberg213202e2013-01-27 00:31:33 +0200703static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
704{
705 u8 *ptr = data, *uuids_start = NULL;
706 struct bt_uuid *uuid;
707
708 if (len < 4)
709 return ptr;
710
711 list_for_each_entry(uuid, &hdev->uuids, list) {
712 u16 uuid16;
713
714 if (uuid->size != 16)
715 continue;
716
717 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
718 if (uuid16 < 0x1100)
719 continue;
720
721 if (uuid16 == PNP_INFO_SVCLASS_ID)
722 continue;
723
724 if (!uuids_start) {
725 uuids_start = ptr;
726 uuids_start[0] = 1;
727 uuids_start[1] = EIR_UUID16_ALL;
728 ptr += 2;
729 }
730
731 /* Stop if not enough space to put next UUID */
732 if ((ptr - data) + sizeof(u16) > len) {
733 uuids_start[1] = EIR_UUID16_SOME;
734 break;
735 }
736
737 *ptr++ = (uuid16 & 0x00ff);
738 *ptr++ = (uuid16 & 0xff00) >> 8;
739 uuids_start[0] += sizeof(uuid16);
740 }
741
742 return ptr;
743}
744
Johan Hedbergcdf19632013-01-27 00:31:34 +0200745static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
746{
747 u8 *ptr = data, *uuids_start = NULL;
748 struct bt_uuid *uuid;
749
750 if (len < 6)
751 return ptr;
752
753 list_for_each_entry(uuid, &hdev->uuids, list) {
754 if (uuid->size != 32)
755 continue;
756
757 if (!uuids_start) {
758 uuids_start = ptr;
759 uuids_start[0] = 1;
760 uuids_start[1] = EIR_UUID32_ALL;
761 ptr += 2;
762 }
763
764 /* Stop if not enough space to put next UUID */
765 if ((ptr - data) + sizeof(u32) > len) {
766 uuids_start[1] = EIR_UUID32_SOME;
767 break;
768 }
769
770 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
771 ptr += sizeof(u32);
772 uuids_start[0] += sizeof(u32);
773 }
774
775 return ptr;
776}
777
Johan Hedbergc00d5752013-01-27 00:31:35 +0200778static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
779{
780 u8 *ptr = data, *uuids_start = NULL;
781 struct bt_uuid *uuid;
782
783 if (len < 18)
784 return ptr;
785
786 list_for_each_entry(uuid, &hdev->uuids, list) {
787 if (uuid->size != 128)
788 continue;
789
790 if (!uuids_start) {
791 uuids_start = ptr;
792 uuids_start[0] = 1;
793 uuids_start[1] = EIR_UUID128_ALL;
794 ptr += 2;
795 }
796
797 /* Stop if not enough space to put next UUID */
798 if ((ptr - data) + 16 > len) {
799 uuids_start[1] = EIR_UUID128_SOME;
800 break;
801 }
802
803 memcpy(ptr, uuid->uuid, 16);
804 ptr += 16;
805 uuids_start[0] += 16;
806 }
807
808 return ptr;
809}
810
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200811static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
812 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300813{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200814 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300815
816 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
817 if (cmd->opcode == opcode)
818 return cmd;
819 }
820
821 return NULL;
822}
823
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200824static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
825 struct hci_dev *hdev,
826 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300827{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200828 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300829
830 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
831 if (cmd->user_data != data)
832 continue;
833 if (cmd->opcode == opcode)
834 return cmd;
835 }
836
837 return NULL;
838}
839
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700840static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
841{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700842 u8 ad_len = 0;
843 size_t name_len;
844
845 name_len = strlen(hdev->dev_name);
846 if (name_len > 0) {
847 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
848
849 if (name_len > max_len) {
850 name_len = max_len;
851 ptr[1] = EIR_NAME_SHORT;
852 } else
853 ptr[1] = EIR_NAME_COMPLETE;
854
855 ptr[0] = name_len + 1;
856
857 memcpy(ptr + 2, hdev->dev_name, name_len);
858
859 ad_len += (name_len + 2);
860 ptr += (name_len + 2);
861 }
862
863 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700864}
865
866static void update_scan_rsp_data(struct hci_request *req)
867{
868 struct hci_dev *hdev = req->hdev;
869 struct hci_cp_le_set_scan_rsp_data cp;
870 u8 len;
871
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700872 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700873 return;
874
875 memset(&cp, 0, sizeof(cp));
876
877 len = create_scan_rsp_data(hdev, cp.data);
878
Johan Hedbergeb438b52013-10-16 15:31:07 +0300879 if (hdev->scan_rsp_data_len == len &&
880 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700881 return;
882
Johan Hedbergeb438b52013-10-16 15:31:07 +0300883 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
884 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700885
886 cp.length = len;
887
888 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
889}
890
Johan Hedberg9a43e252013-10-20 19:00:07 +0300891static u8 get_adv_discov_flags(struct hci_dev *hdev)
892{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200893 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300894
895 /* If there's a pending mgmt command the flags will not yet have
896 * their final values, so check for this first.
897 */
898 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
899 if (cmd) {
900 struct mgmt_mode *cp = cmd->param;
901 if (cp->val == 0x01)
902 return LE_AD_GENERAL;
903 else if (cp->val == 0x02)
904 return LE_AD_LIMITED;
905 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700906 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300907 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700908 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300909 return LE_AD_GENERAL;
910 }
911
912 return 0;
913}
914
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700915static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700916{
917 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700918
Johan Hedberg9a43e252013-10-20 19:00:07 +0300919 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700920
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700921 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700922 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700923
924 if (flags) {
925 BT_DBG("adv flags 0x%02x", flags);
926
927 ptr[0] = 2;
928 ptr[1] = EIR_FLAGS;
929 ptr[2] = flags;
930
931 ad_len += 3;
932 ptr += 3;
933 }
934
935 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
936 ptr[0] = 2;
937 ptr[1] = EIR_TX_POWER;
938 ptr[2] = (u8) hdev->adv_tx_power;
939
940 ad_len += 3;
941 ptr += 3;
942 }
943
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700944 return ad_len;
945}
946
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700947static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700948{
949 struct hci_dev *hdev = req->hdev;
950 struct hci_cp_le_set_adv_data cp;
951 u8 len;
952
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700953 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700954 return;
955
956 memset(&cp, 0, sizeof(cp));
957
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700958 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700959
960 if (hdev->adv_data_len == len &&
961 memcmp(cp.data, hdev->adv_data, len) == 0)
962 return;
963
964 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
965 hdev->adv_data_len = len;
966
967 cp.length = len;
968
969 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
970}
971
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300972int mgmt_update_adv_data(struct hci_dev *hdev)
973{
974 struct hci_request req;
975
976 hci_req_init(&req, hdev);
977 update_adv_data(&req);
978
979 return hci_req_run(&req, NULL);
980}
981
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300982static void create_eir(struct hci_dev *hdev, u8 *data)
983{
984 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300985 size_t name_len;
986
987 name_len = strlen(hdev->dev_name);
988
989 if (name_len > 0) {
990 /* EIR Data type */
991 if (name_len > 48) {
992 name_len = 48;
993 ptr[1] = EIR_NAME_SHORT;
994 } else
995 ptr[1] = EIR_NAME_COMPLETE;
996
997 /* EIR Data length */
998 ptr[0] = name_len + 1;
999
1000 memcpy(ptr + 2, hdev->dev_name, name_len);
1001
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001002 ptr += (name_len + 2);
1003 }
1004
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001005 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001006 ptr[0] = 2;
1007 ptr[1] = EIR_TX_POWER;
1008 ptr[2] = (u8) hdev->inq_tx_power;
1009
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001010 ptr += 3;
1011 }
1012
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001013 if (hdev->devid_source > 0) {
1014 ptr[0] = 9;
1015 ptr[1] = EIR_DEVICE_ID;
1016
1017 put_unaligned_le16(hdev->devid_source, ptr + 2);
1018 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1019 put_unaligned_le16(hdev->devid_product, ptr + 6);
1020 put_unaligned_le16(hdev->devid_version, ptr + 8);
1021
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001022 ptr += 10;
1023 }
1024
Johan Hedberg213202e2013-01-27 00:31:33 +02001025 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001026 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001027 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001028}
1029
Johan Hedberg890ea892013-03-15 17:06:52 -05001030static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001031{
Johan Hedberg890ea892013-03-15 17:06:52 -05001032 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001033 struct hci_cp_write_eir cp;
1034
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001035 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001036 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001037
Johan Hedberg976eb202012-10-24 21:12:01 +03001038 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001039 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001040
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001041 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001042 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001043
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001044 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001045 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001046
1047 memset(&cp, 0, sizeof(cp));
1048
1049 create_eir(hdev, cp.data);
1050
1051 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001052 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001053
1054 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1055
Johan Hedberg890ea892013-03-15 17:06:52 -05001056 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001057}
1058
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001059static u8 get_service_classes(struct hci_dev *hdev)
1060{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001061 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001062 u8 val = 0;
1063
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001064 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001065 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001066
1067 return val;
1068}
1069
Johan Hedberg890ea892013-03-15 17:06:52 -05001070static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001071{
Johan Hedberg890ea892013-03-15 17:06:52 -05001072 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001073 u8 cod[3];
1074
1075 BT_DBG("%s", hdev->name);
1076
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001077 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001078 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001079
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001080 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001081 return;
1082
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001083 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001084 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001085
1086 cod[0] = hdev->minor_class;
1087 cod[1] = hdev->major_class;
1088 cod[2] = get_service_classes(hdev);
1089
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001090 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001091 cod[1] |= 0x20;
1092
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001093 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001095
Johan Hedberg890ea892013-03-15 17:06:52 -05001096 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001097}
1098
Johan Hedberga4858cb2014-02-25 19:56:31 +02001099static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001100{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001101 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001102
1103 /* If there's a pending mgmt command the flag will not yet have
1104 * it's final value, so check for this first.
1105 */
1106 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1107 if (cmd) {
1108 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001109 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001110 }
1111
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001112 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001113}
1114
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001115static void disable_advertising(struct hci_request *req)
1116{
1117 u8 enable = 0x00;
1118
1119 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1120}
1121
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001122static void enable_advertising(struct hci_request *req)
1123{
1124 struct hci_dev *hdev = req->hdev;
1125 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001126 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001127 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001128
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001129 if (hci_conn_num(hdev, LE_LINK) > 0)
1130 return;
1131
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001132 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001133 disable_advertising(req);
1134
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001135 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001136 * hci_update_random_address knows that it's safe to go ahead
1137 * and write a new random address. The flag will be set back on
1138 * as soon as the SET_ADV_ENABLE HCI command completes.
1139 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001140 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001141
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001142 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001143 connectable = true;
1144 else
1145 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001146
Johan Hedberga4858cb2014-02-25 19:56:31 +02001147 /* Set require_privacy to true only when non-connectable
1148 * advertising is used. In that case it is fine to use a
1149 * non-resolvable private address.
1150 */
1151 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001152 return;
1153
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001154 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001155 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1156 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001157 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001158 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001159 cp.channel_map = hdev->le_adv_channel_map;
1160
1161 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1162
1163 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1164}
1165
Johan Hedberg7d785252011-12-15 00:47:39 +02001166static void service_cache_off(struct work_struct *work)
1167{
1168 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001169 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001170 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001171
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001172 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001173 return;
1174
Johan Hedberg890ea892013-03-15 17:06:52 -05001175 hci_req_init(&req, hdev);
1176
Johan Hedberg7d785252011-12-15 00:47:39 +02001177 hci_dev_lock(hdev);
1178
Johan Hedberg890ea892013-03-15 17:06:52 -05001179 update_eir(&req);
1180 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001181
1182 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001183
1184 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001185}
1186
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001187static void rpa_expired(struct work_struct *work)
1188{
1189 struct hci_dev *hdev = container_of(work, struct hci_dev,
1190 rpa_expired.work);
1191 struct hci_request req;
1192
1193 BT_DBG("");
1194
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001195 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001196
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001197 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001198 return;
1199
1200 /* The generation of a new RPA and programming it into the
1201 * controller happens in the enable_advertising() function.
1202 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001203 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001204 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001205 hci_req_run(&req, NULL);
1206}
1207
Johan Hedberg6a919082012-02-28 06:17:26 +02001208static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001209{
Marcel Holtmann238be782015-03-13 02:11:06 -07001210 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001211 return;
1212
Johan Hedberg4f87da82012-03-02 19:55:56 +02001213 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001214 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001215
Johan Hedberg4f87da82012-03-02 19:55:56 +02001216 /* Non-mgmt controlled devices get this bit set
1217 * implicitly so that pairing works for them, however
1218 * for mgmt we require user-space to explicitly enable
1219 * it
1220 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001221 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001222}
1223
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001224static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001225 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001226{
1227 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001228
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001229 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001230
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001231 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001232
Johan Hedberg03811012010-12-08 00:21:06 +02001233 memset(&rp, 0, sizeof(rp));
1234
Johan Hedberg03811012010-12-08 00:21:06 +02001235 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001236
1237 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001238 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001239
1240 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1241 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1242
1243 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001244
1245 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001246 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001247
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001248 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001249
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001250 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1251 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001252}
1253
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001254static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001255{
1256 sock_put(cmd->sk);
1257 kfree(cmd->param);
1258 kfree(cmd);
1259}
1260
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001261static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1262 struct hci_dev *hdev,
1263 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001264{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001265 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001266
Johan Hedbergfca20012014-06-28 17:54:05 +03001267 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001268 if (!cmd)
1269 return NULL;
1270
1271 cmd->opcode = opcode;
1272 cmd->index = hdev->id;
1273
Johan Hedberg323b0b82014-12-05 13:36:01 +02001274 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001275 if (!cmd->param) {
1276 kfree(cmd);
1277 return NULL;
1278 }
1279
Johan Hedberg323b0b82014-12-05 13:36:01 +02001280 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001281
1282 cmd->sk = sk;
1283 sock_hold(sk);
1284
1285 list_add(&cmd->list, &hdev->mgmt_pending);
1286
1287 return cmd;
1288}
1289
1290static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001291 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001292 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001293 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001294{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001295 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001296
Andre Guedesa3d09352013-02-01 11:21:30 -03001297 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001298 if (opcode > 0 && cmd->opcode != opcode)
1299 continue;
1300
1301 cb(cmd, data);
1302 }
1303}
1304
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001305static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001306{
1307 list_del(&cmd->list);
1308 mgmt_pending_free(cmd);
1309}
1310
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001311static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001312{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001313 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001314
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001315 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1316 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001317}
1318
Marcel Holtmann1904a852015-01-11 13:50:44 -08001319static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001320{
1321 BT_DBG("%s status 0x%02x", hdev->name, status);
1322
Johan Hedberga3172b72014-02-28 09:33:44 +02001323 if (hci_conn_count(hdev) == 0) {
1324 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001326 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001327}
1328
Johan Hedberg23a48092014-07-08 16:05:06 +03001329static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001330{
1331 struct hci_dev *hdev = req->hdev;
1332 struct hci_cp_remote_name_req_cancel cp;
1333 struct inquiry_entry *e;
1334
1335 switch (hdev->discovery.state) {
1336 case DISCOVERY_FINDING:
1337 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1338 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1339 } else {
1340 cancel_delayed_work(&hdev->le_scan_disable);
1341 hci_req_add_le_scan_disable(req);
1342 }
1343
Johan Hedberg23a48092014-07-08 16:05:06 +03001344 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001345
1346 case DISCOVERY_RESOLVING:
1347 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1348 NAME_PENDING);
1349 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001350 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001351
1352 bacpy(&cp.bdaddr, &e->data.bdaddr);
1353 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1354 &cp);
1355
Johan Hedberg23a48092014-07-08 16:05:06 +03001356 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001357
1358 default:
1359 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001360 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001361 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001362 return true;
1363 }
1364
Johan Hedberg21a60d32014-06-10 14:05:58 +03001365 break;
1366 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001367
1368 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001369}
1370
Johan Hedberg8b064a32014-02-24 14:52:22 +02001371static int clean_up_hci_state(struct hci_dev *hdev)
1372{
1373 struct hci_request req;
1374 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001375 bool discov_stopped;
1376 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001377
1378 hci_req_init(&req, hdev);
1379
1380 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1381 test_bit(HCI_PSCAN, &hdev->flags)) {
1382 u8 scan = 0x00;
1383 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1384 }
1385
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001386 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001387 disable_advertising(&req);
1388
Johan Hedberg23a48092014-07-08 16:05:06 +03001389 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001390
1391 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1392 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001393 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001394
Johan Hedbergc9910d02014-02-27 14:35:12 +02001395 switch (conn->state) {
1396 case BT_CONNECTED:
1397 case BT_CONFIG:
1398 dc.handle = cpu_to_le16(conn->handle);
1399 dc.reason = 0x15; /* Terminated due to Power Off */
1400 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1401 break;
1402 case BT_CONNECT:
1403 if (conn->type == LE_LINK)
1404 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1405 0, NULL);
1406 else if (conn->type == ACL_LINK)
1407 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1408 6, &conn->dst);
1409 break;
1410 case BT_CONNECT2:
1411 bacpy(&rej.bdaddr, &conn->dst);
1412 rej.reason = 0x15; /* Terminated due to Power Off */
1413 if (conn->type == ACL_LINK)
1414 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1415 sizeof(rej), &rej);
1416 else if (conn->type == SCO_LINK)
1417 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1418 sizeof(rej), &rej);
1419 break;
1420 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001421 }
1422
Johan Hedberg23a48092014-07-08 16:05:06 +03001423 err = hci_req_run(&req, clean_up_hci_complete);
1424 if (!err && discov_stopped)
1425 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1426
1427 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001428}
1429
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001430static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001431 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001432{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001433 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001434 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001435 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001436
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001437 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001438
Johan Hedberga7e80f22013-01-09 16:05:19 +02001439 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001440 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1441 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001442
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001443 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001444
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001445 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001446 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1447 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001448 goto failed;
1449 }
1450
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001451 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001452 cancel_delayed_work(&hdev->power_off);
1453
1454 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001455 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1456 data, len);
1457 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001458 goto failed;
1459 }
1460 }
1461
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001462 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001463 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001464 goto failed;
1465 }
1466
Johan Hedberg03811012010-12-08 00:21:06 +02001467 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1468 if (!cmd) {
1469 err = -ENOMEM;
1470 goto failed;
1471 }
1472
Johan Hedberg8b064a32014-02-24 14:52:22 +02001473 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001474 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001475 err = 0;
1476 } else {
1477 /* Disconnect connections, stop scans, etc */
1478 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001479 if (!err)
1480 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1481 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001482
Johan Hedberg8b064a32014-02-24 14:52:22 +02001483 /* ENODATA means there were no HCI commands queued */
1484 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001485 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001486 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1487 err = 0;
1488 }
1489 }
Johan Hedberg03811012010-12-08 00:21:06 +02001490
1491failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001492 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001493 return err;
1494}
1495
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001496static int new_settings(struct hci_dev *hdev, struct sock *skip)
1497{
1498 __le32 ev;
1499
1500 ev = cpu_to_le32(get_current_settings(hdev));
1501
1502 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1503}
1504
Johan Hedberg91a668b2014-07-09 13:28:26 +03001505int mgmt_new_settings(struct hci_dev *hdev)
1506{
1507 return new_settings(hdev, NULL);
1508}
1509
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001510struct cmd_lookup {
1511 struct sock *sk;
1512 struct hci_dev *hdev;
1513 u8 mgmt_status;
1514};
1515
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001516static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001517{
1518 struct cmd_lookup *match = data;
1519
1520 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1521
1522 list_del(&cmd->list);
1523
1524 if (match->sk == NULL) {
1525 match->sk = cmd->sk;
1526 sock_hold(match->sk);
1527 }
1528
1529 mgmt_pending_free(cmd);
1530}
1531
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001532static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001533{
1534 u8 *status = data;
1535
Johan Hedberga69e8372015-03-06 21:08:53 +02001536 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001537 mgmt_pending_remove(cmd);
1538}
1539
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001540static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001541{
1542 if (cmd->cmd_complete) {
1543 u8 *status = data;
1544
1545 cmd->cmd_complete(cmd, *status);
1546 mgmt_pending_remove(cmd);
1547
1548 return;
1549 }
1550
1551 cmd_status_rsp(cmd, data);
1552}
1553
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001554static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001555{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001556 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1557 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001558}
1559
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001560static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001561{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001562 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1563 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001564}
1565
Johan Hedberge6fe7982013-10-02 15:45:22 +03001566static u8 mgmt_bredr_support(struct hci_dev *hdev)
1567{
1568 if (!lmp_bredr_capable(hdev))
1569 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001570 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001571 return MGMT_STATUS_REJECTED;
1572 else
1573 return MGMT_STATUS_SUCCESS;
1574}
1575
1576static u8 mgmt_le_support(struct hci_dev *hdev)
1577{
1578 if (!lmp_le_capable(hdev))
1579 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001580 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001581 return MGMT_STATUS_REJECTED;
1582 else
1583 return MGMT_STATUS_SUCCESS;
1584}
1585
Marcel Holtmann1904a852015-01-11 13:50:44 -08001586static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1587 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001588{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001589 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001590 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001591 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001592 bool changed;
1593
1594 BT_DBG("status 0x%02x", status);
1595
1596 hci_dev_lock(hdev);
1597
1598 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1599 if (!cmd)
1600 goto unlock;
1601
1602 if (status) {
1603 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001604 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001605 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001606 goto remove_cmd;
1607 }
1608
1609 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001610 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001611 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001612
1613 if (hdev->discov_timeout > 0) {
1614 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1615 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1616 to);
1617 }
1618 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001619 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001620 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001621
1622 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1623
1624 if (changed)
1625 new_settings(hdev, cmd->sk);
1626
Marcel Holtmann970ba522013-10-15 06:33:57 -07001627 /* When the discoverable mode gets changed, make sure
1628 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001629 * bit correctly set. Also update page scan based on whitelist
1630 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001631 */
1632 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001633 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001634 update_class(&req);
1635 hci_req_run(&req, NULL);
1636
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001637remove_cmd:
1638 mgmt_pending_remove(cmd);
1639
1640unlock:
1641 hci_dev_unlock(hdev);
1642}
1643
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001644static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001645 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001646{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001647 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001648 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001649 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001650 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001651 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001652 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001653
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001654 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001655
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001656 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1657 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001658 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1659 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001660
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001661 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001662 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1663 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001664
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001665 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001666
1667 /* Disabling discoverable requires that no timeout is set,
1668 * and enabling limited discoverable requires a timeout.
1669 */
1670 if ((cp->val == 0x00 && timeout > 0) ||
1671 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001672 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1673 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001674
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001675 hci_dev_lock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001676
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001677 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001678 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1679 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001680 goto failed;
1681 }
1682
1683 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001684 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001685 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1686 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001687 goto failed;
1688 }
1689
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001690 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001691 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1692 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001693 goto failed;
1694 }
1695
1696 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001697 bool changed = false;
1698
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001699 /* Setting limited discoverable when powered off is
1700 * not a valid operation since it requires a timeout
1701 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1702 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001703 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001704 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001705 changed = true;
1706 }
1707
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001708 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001709 if (err < 0)
1710 goto failed;
1711
1712 if (changed)
1713 err = new_settings(hdev, sk);
1714
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001715 goto failed;
1716 }
1717
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001718 /* If the current mode is the same, then just update the timeout
1719 * value with the new value. And if only the timeout gets updated,
1720 * then no need for any HCI transactions.
1721 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001722 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1723 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1724 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001725 cancel_delayed_work(&hdev->discov_off);
1726 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001727
Marcel Holtmann36261542013-10-15 08:28:51 -07001728 if (cp->val && hdev->discov_timeout > 0) {
1729 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001730 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001731 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001732 }
1733
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001734 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001735 goto failed;
1736 }
1737
1738 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1739 if (!cmd) {
1740 err = -ENOMEM;
1741 goto failed;
1742 }
1743
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001744 /* Cancel any potential discoverable timeout that might be
1745 * still active and store new timeout value. The arming of
1746 * the timeout happens in the complete handler.
1747 */
1748 cancel_delayed_work(&hdev->discov_off);
1749 hdev->discov_timeout = timeout;
1750
Johan Hedbergb456f872013-10-19 23:38:22 +03001751 /* Limited discoverable mode */
1752 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001753 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001754 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001755 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001756
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001757 hci_req_init(&req, hdev);
1758
Johan Hedberg9a43e252013-10-20 19:00:07 +03001759 /* The procedure for LE-only controllers is much simpler - just
1760 * update the advertising data.
1761 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001762 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001763 goto update_ad;
1764
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001765 scan = SCAN_PAGE;
1766
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001767 if (cp->val) {
1768 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001769
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001770 if (cp->val == 0x02) {
1771 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001772 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001773 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1774 hci_cp.iac_lap[1] = 0x8b;
1775 hci_cp.iac_lap[2] = 0x9e;
1776 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1777 hci_cp.iac_lap[4] = 0x8b;
1778 hci_cp.iac_lap[5] = 0x9e;
1779 } else {
1780 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001781 hci_cp.num_iac = 1;
1782 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1783 hci_cp.iac_lap[1] = 0x8b;
1784 hci_cp.iac_lap[2] = 0x9e;
1785 }
1786
1787 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1788 (hci_cp.num_iac * 3) + 1, &hci_cp);
1789
1790 scan |= SCAN_INQUIRY;
1791 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001792 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001793 }
1794
1795 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001796
Johan Hedberg9a43e252013-10-20 19:00:07 +03001797update_ad:
1798 update_adv_data(&req);
1799
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001800 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001801 if (err < 0)
1802 mgmt_pending_remove(cmd);
1803
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001804failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001805 hci_dev_unlock(hdev);
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001806 return err;
1807}
1808
Johan Hedberg406d7802013-03-15 17:07:09 -05001809static void write_fast_connectable(struct hci_request *req, bool enable)
1810{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001811 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001812 struct hci_cp_write_page_scan_activity acp;
1813 u8 type;
1814
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001815 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001816 return;
1817
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001818 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1819 return;
1820
Johan Hedberg406d7802013-03-15 17:07:09 -05001821 if (enable) {
1822 type = PAGE_SCAN_TYPE_INTERLACED;
1823
1824 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001825 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001826 } else {
1827 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1828
1829 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001830 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001831 }
1832
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001833 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001834
Johan Hedbergbd98b992013-03-15 17:07:13 -05001835 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1836 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1837 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1838 sizeof(acp), &acp);
1839
1840 if (hdev->page_scan_type != type)
1841 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001842}
1843
Marcel Holtmann1904a852015-01-11 13:50:44 -08001844static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1845 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001846{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001847 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001848 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001849 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001850
1851 BT_DBG("status 0x%02x", status);
1852
1853 hci_dev_lock(hdev);
1854
1855 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1856 if (!cmd)
1857 goto unlock;
1858
Johan Hedberg37438c12013-10-14 16:20:05 +03001859 if (status) {
1860 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001861 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001862 goto remove_cmd;
1863 }
1864
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001865 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001866 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001867 conn_changed = !hci_dev_test_and_set_flag(hdev,
1868 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001869 discov_changed = false;
1870 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001871 conn_changed = hci_dev_test_and_clear_flag(hdev,
1872 HCI_CONNECTABLE);
1873 discov_changed = hci_dev_test_and_clear_flag(hdev,
1874 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001875 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001876
Johan Hedberg2b76f452013-03-15 17:07:04 -05001877 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1878
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001879 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001880 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001881 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001882 if (discov_changed)
1883 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001884 hci_update_background_scan(hdev);
1885 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001886
Johan Hedberg37438c12013-10-14 16:20:05 +03001887remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001888 mgmt_pending_remove(cmd);
1889
1890unlock:
1891 hci_dev_unlock(hdev);
1892}
1893
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001894static int set_connectable_update_settings(struct hci_dev *hdev,
1895 struct sock *sk, u8 val)
1896{
1897 bool changed = false;
1898 int err;
1899
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001900 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001901 changed = true;
1902
1903 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001904 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001905 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001906 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1907 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001908 }
1909
1910 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1911 if (err < 0)
1912 return err;
1913
Johan Hedberg562064e2014-07-08 16:35:34 +03001914 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001915 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001916 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001917 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001918 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001919
1920 return 0;
1921}
1922
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001923static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001924 u16 len)
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001925{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001926 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001927 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001928 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001929 u8 scan;
Johan Hedbergf7b64e62010-12-13 21:07:06 +02001930 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001931
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001932 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001933
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001934 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1935 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001936 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1937 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001938
Johan Hedberga7e80f22013-01-09 16:05:19 +02001939 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001940 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1941 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001942
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001943 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001944
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001945 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001946 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001947 goto failed;
1948 }
1949
1950 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001951 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001952 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1953 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001954 goto failed;
1955 }
1956
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001957 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1958 if (!cmd) {
1959 err = -ENOMEM;
1960 goto failed;
1961 }
1962
Johan Hedberg2b76f452013-03-15 17:07:04 -05001963 hci_req_init(&req, hdev);
1964
Johan Hedberg9a43e252013-10-20 19:00:07 +03001965 /* If BR/EDR is not enabled and we disable advertising as a
1966 * by-product of disabling connectable, we need to update the
1967 * advertising flags.
1968 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001969 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03001970 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001971 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
1972 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03001973 }
1974 update_adv_data(&req);
1975 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001976 if (cp->val) {
1977 scan = SCAN_PAGE;
1978 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001979 /* If we don't have any whitelist entries just
1980 * disable all scanning. If there are entries
1981 * and we had both page and inquiry scanning
1982 * enabled then fall back to only page scanning.
1983 * Otherwise no changes are needed.
1984 */
1985 if (list_empty(&hdev->whitelist))
1986 scan = SCAN_DISABLED;
1987 else if (test_bit(HCI_ISCAN, &hdev->flags))
1988 scan = SCAN_PAGE;
1989 else
1990 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001991
1992 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001993 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001994 cancel_delayed_work(&hdev->discov_off);
1995 }
1996
1997 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1998 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001999
Johan Hedberg3bd27242014-07-28 20:53:58 +03002000no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002001 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002002 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002003 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002004
Johan Hedberg2b76f452013-03-15 17:07:04 -05002005 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002006 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002007 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002008 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002009 err = set_connectable_update_settings(hdev, sk,
2010 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002011 goto failed;
2012 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002013
2014failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002015 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002016 return err;
2017}
2018
Johan Hedbergb2939472014-07-30 09:22:23 +03002019static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002020 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002021{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002022 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002023 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002024 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002025
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002026 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002027
Johan Hedberga7e80f22013-01-09 16:05:19 +02002028 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002029 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2030 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002031
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002032 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002033
2034 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002035 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002036 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002037 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002038
Johan Hedbergb2939472014-07-30 09:22:23 +03002039 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002040 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002041 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002042
Marcel Holtmann55594352013-10-06 16:11:57 -07002043 if (changed)
2044 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002045
Marcel Holtmann55594352013-10-06 16:11:57 -07002046unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002047 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002048 return err;
2049}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002050
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002051static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2052 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002053{
2054 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002055 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002056 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002057 int err;
2058
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002059 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002060
Johan Hedberge6fe7982013-10-02 15:45:22 +03002061 status = mgmt_bredr_support(hdev);
2062 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002063 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2064 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002065
Johan Hedberga7e80f22013-01-09 16:05:19 +02002066 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002067 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2068 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002069
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002070 hci_dev_lock(hdev);
2071
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002072 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002073 bool changed = false;
2074
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002075 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002076 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002077 changed = true;
2078 }
2079
2080 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2081 if (err < 0)
2082 goto failed;
2083
2084 if (changed)
2085 err = new_settings(hdev, sk);
2086
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002087 goto failed;
2088 }
2089
2090 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002091 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2092 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002093 goto failed;
2094 }
2095
2096 val = !!cp->val;
2097
2098 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2099 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2100 goto failed;
2101 }
2102
2103 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2104 if (!cmd) {
2105 err = -ENOMEM;
2106 goto failed;
2107 }
2108
2109 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2110 if (err < 0) {
2111 mgmt_pending_remove(cmd);
2112 goto failed;
2113 }
2114
2115failed:
2116 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002117 return err;
2118}
2119
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002120static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002121{
2122 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002123 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002124 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002125 int err;
2126
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002127 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002128
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002129 status = mgmt_bredr_support(hdev);
2130 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002131 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002132
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002133 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002134 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2135 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002136
Johan Hedberga7e80f22013-01-09 16:05:19 +02002137 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002138 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2139 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002140
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002141 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002142
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002143 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002144 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002145
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002146 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002147 changed = !hci_dev_test_and_set_flag(hdev,
2148 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002149 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002150 changed = hci_dev_test_and_clear_flag(hdev,
2151 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002152 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002153 changed = hci_dev_test_and_clear_flag(hdev,
2154 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002155 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002156 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002157 }
2158
2159 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2160 if (err < 0)
2161 goto failed;
2162
2163 if (changed)
2164 err = new_settings(hdev, sk);
2165
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002166 goto failed;
2167 }
2168
Johan Hedberg94d52da2015-02-19 17:38:06 +02002169 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002170 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2171 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002172 goto failed;
2173 }
2174
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002175 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002176 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2177 goto failed;
2178 }
2179
2180 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2181 if (!cmd) {
2182 err = -ENOMEM;
2183 goto failed;
2184 }
2185
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002186 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002187 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2188 sizeof(cp->val), &cp->val);
2189
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002190 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002191 if (err < 0) {
2192 mgmt_pending_remove(cmd);
2193 goto failed;
2194 }
2195
2196failed:
2197 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002198 return err;
2199}
2200
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002201static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002202{
2203 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002204 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002205 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002206 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002207
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002208 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002209
Johan Hedberge6fe7982013-10-02 15:45:22 +03002210 status = mgmt_bredr_support(hdev);
2211 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002212 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002213
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002214 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002215 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2216 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002217
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002218 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002219 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2220 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002221
Johan Hedberga7e80f22013-01-09 16:05:19 +02002222 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002223 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2224 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002225
Marcel Holtmannee392692013-10-01 22:59:23 -07002226 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002227
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002228 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002229 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2230 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002231 goto unlock;
2232 }
2233
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002234 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002235 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002236 } else {
2237 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002238 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2239 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002240 goto unlock;
2241 }
2242
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002243 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002244 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002245
2246 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2247 if (err < 0)
2248 goto unlock;
2249
2250 if (changed)
2251 err = new_settings(hdev, sk);
2252
2253unlock:
2254 hci_dev_unlock(hdev);
2255 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002256}
2257
Marcel Holtmann1904a852015-01-11 13:50:44 -08002258static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002259{
2260 struct cmd_lookup match = { NULL, hdev };
2261
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302262 hci_dev_lock(hdev);
2263
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002264 if (status) {
2265 u8 mgmt_err = mgmt_status(status);
2266
2267 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2268 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302269 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002270 }
2271
2272 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2273
2274 new_settings(hdev, match.sk);
2275
2276 if (match.sk)
2277 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002278
2279 /* Make sure the controller has a good default for
2280 * advertising data. Restrict the update to when LE
2281 * has actually been enabled. During power on, the
2282 * update in powered_update_hci will take care of it.
2283 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002284 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002285 struct hci_request req;
2286
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002287 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002288 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002289 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002290 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002291 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002292 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302293
2294unlock:
2295 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002296}
2297
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002298static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002299{
2300 struct mgmt_mode *cp = data;
2301 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002302 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002303 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002304 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002305 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002307 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002308
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002309 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002310 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2311 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002312
Johan Hedberga7e80f22013-01-09 16:05:19 +02002313 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002314 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2315 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002316
Johan Hedbergc73eee92013-04-19 18:35:21 +03002317 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002318 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002319 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2320 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002321
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002322 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002323
2324 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002325 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002326
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002327 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002328 bool changed = false;
2329
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002330 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002331 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002332 changed = true;
2333 }
2334
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002335 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002336 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002337 changed = true;
2338 }
2339
Johan Hedberg06199cf2012-02-22 16:37:11 +02002340 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2341 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002342 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002343
2344 if (changed)
2345 err = new_settings(hdev, sk);
2346
Johan Hedberg1de028c2012-02-29 19:55:35 -08002347 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002348 }
2349
Johan Hedberg4375f102013-09-25 13:26:10 +03002350 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2351 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002352 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2353 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002354 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002355 }
2356
2357 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2358 if (!cmd) {
2359 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002360 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002361 }
2362
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002363 hci_req_init(&req, hdev);
2364
Johan Hedberg06199cf2012-02-22 16:37:11 +02002365 memset(&hci_cp, 0, sizeof(hci_cp));
2366
2367 if (val) {
2368 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002369 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002370 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002371 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002372 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002373 }
2374
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002375 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2376 &hci_cp);
2377
2378 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302379 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002380 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002381
Johan Hedberg1de028c2012-02-29 19:55:35 -08002382unlock:
2383 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002384 return err;
2385}
2386
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002387/* This is a helper function to test for pending mgmt commands that can
2388 * cause CoD or EIR HCI commands. We can only allow one such pending
2389 * mgmt command at a time since otherwise we cannot easily track what
2390 * the current values are, will be, and based on that calculate if a new
2391 * HCI command needs to be sent and if yes with what value.
2392 */
2393static bool pending_eir_or_class(struct hci_dev *hdev)
2394{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002395 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002396
2397 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2398 switch (cmd->opcode) {
2399 case MGMT_OP_ADD_UUID:
2400 case MGMT_OP_REMOVE_UUID:
2401 case MGMT_OP_SET_DEV_CLASS:
2402 case MGMT_OP_SET_POWERED:
2403 return true;
2404 }
2405 }
2406
2407 return false;
2408}
2409
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002410static const u8 bluetooth_base_uuid[] = {
2411 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2412 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2413};
2414
2415static u8 get_uuid_size(const u8 *uuid)
2416{
2417 u32 val;
2418
2419 if (memcmp(uuid, bluetooth_base_uuid, 12))
2420 return 128;
2421
2422 val = get_unaligned_le32(&uuid[12]);
2423 if (val > 0xffff)
2424 return 32;
2425
2426 return 16;
2427}
2428
Johan Hedberg92da6092013-03-15 17:06:55 -05002429static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2430{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002431 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002432
2433 hci_dev_lock(hdev);
2434
2435 cmd = mgmt_pending_find(mgmt_op, hdev);
2436 if (!cmd)
2437 goto unlock;
2438
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002439 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2440 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002441
2442 mgmt_pending_remove(cmd);
2443
2444unlock:
2445 hci_dev_unlock(hdev);
2446}
2447
Marcel Holtmann1904a852015-01-11 13:50:44 -08002448static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002449{
2450 BT_DBG("status 0x%02x", status);
2451
2452 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2453}
2454
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002455static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002456{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002457 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002458 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002459 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002460 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002461 int err;
2462
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002463 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002464
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002465 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002466
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002467 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002468 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2469 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002470 goto failed;
2471 }
2472
Andre Guedes92c4c202012-06-07 19:05:44 -03002473 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002474 if (!uuid) {
2475 err = -ENOMEM;
2476 goto failed;
2477 }
2478
2479 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002480 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002481 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482
Johan Hedbergde66aa62013-01-27 00:31:27 +02002483 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002484
Johan Hedberg890ea892013-03-15 17:06:52 -05002485 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002486
Johan Hedberg890ea892013-03-15 17:06:52 -05002487 update_class(&req);
2488 update_eir(&req);
2489
Johan Hedberg92da6092013-03-15 17:06:55 -05002490 err = hci_req_run(&req, add_uuid_complete);
2491 if (err < 0) {
2492 if (err != -ENODATA)
2493 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002494
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002495 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2496 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002497 goto failed;
2498 }
2499
2500 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002501 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002502 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002503 goto failed;
2504 }
2505
2506 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002507
2508failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002509 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002510 return err;
2511}
2512
Johan Hedberg24b78d02012-02-23 23:24:30 +02002513static bool enable_service_cache(struct hci_dev *hdev)
2514{
2515 if (!hdev_is_powered(hdev))
2516 return false;
2517
Marcel Holtmann238be782015-03-13 02:11:06 -07002518 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002519 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2520 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002521 return true;
2522 }
2523
2524 return false;
2525}
2526
Marcel Holtmann1904a852015-01-11 13:50:44 -08002527static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002528{
2529 BT_DBG("status 0x%02x", status);
2530
2531 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2532}
2533
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002534static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002535 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002536{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002537 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002538 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002539 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002540 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 -05002541 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002542 int err, found;
2543
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002544 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002545
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002546 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002547
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002548 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002549 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2550 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002551 goto unlock;
2552 }
2553
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002554 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002555 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002556
Johan Hedberg24b78d02012-02-23 23:24:30 +02002557 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002558 err = mgmt_cmd_complete(sk, hdev->id,
2559 MGMT_OP_REMOVE_UUID,
2560 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002561 goto unlock;
2562 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002563
Johan Hedberg9246a862012-02-23 21:33:16 +02002564 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002565 }
2566
2567 found = 0;
2568
Johan Hedberg056341c2013-01-27 00:31:30 +02002569 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002570 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2571 continue;
2572
2573 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002574 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002575 found++;
2576 }
2577
2578 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002579 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2580 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002581 goto unlock;
2582 }
2583
Johan Hedberg9246a862012-02-23 21:33:16 +02002584update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002585 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002586
Johan Hedberg890ea892013-03-15 17:06:52 -05002587 update_class(&req);
2588 update_eir(&req);
2589
Johan Hedberg92da6092013-03-15 17:06:55 -05002590 err = hci_req_run(&req, remove_uuid_complete);
2591 if (err < 0) {
2592 if (err != -ENODATA)
2593 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002594
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002595 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2596 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002597 goto unlock;
2598 }
2599
2600 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002601 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002602 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002603 goto unlock;
2604 }
2605
2606 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002607
2608unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002609 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002610 return err;
2611}
2612
Marcel Holtmann1904a852015-01-11 13:50:44 -08002613static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002614{
2615 BT_DBG("status 0x%02x", status);
2616
2617 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2618}
2619
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002620static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002621 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002622{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002623 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002624 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002625 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002626 int err;
2627
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002628 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002629
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002630 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002631 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2632 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002633
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002634 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002635
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002636 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002637 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2638 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002639 goto unlock;
2640 }
2641
2642 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002643 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2644 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002645 goto unlock;
2646 }
2647
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002648 hdev->major_class = cp->major;
2649 hdev->minor_class = cp->minor;
2650
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002651 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002652 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2653 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002654 goto unlock;
2655 }
2656
Johan Hedberg890ea892013-03-15 17:06:52 -05002657 hci_req_init(&req, hdev);
2658
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002659 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002660 hci_dev_unlock(hdev);
2661 cancel_delayed_work_sync(&hdev->service_cache);
2662 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002663 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002664 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002665
Johan Hedberg890ea892013-03-15 17:06:52 -05002666 update_class(&req);
2667
Johan Hedberg92da6092013-03-15 17:06:55 -05002668 err = hci_req_run(&req, set_class_complete);
2669 if (err < 0) {
2670 if (err != -ENODATA)
2671 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002672
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002673 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2674 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002675 goto unlock;
2676 }
2677
2678 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002679 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002680 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002681 goto unlock;
2682 }
2683
2684 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002685
Johan Hedbergb5235a62012-02-21 14:32:24 +02002686unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002687 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002688 return err;
2689}
2690
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002691static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002692 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002693{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002694 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002695 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2696 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002697 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002698 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002699 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002700
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002701 BT_DBG("request for %s", hdev->name);
2702
2703 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002704 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2705 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002706
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002707 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002708 if (key_count > max_key_count) {
2709 BT_ERR("load_link_keys: too big key_count value %u",
2710 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002711 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2712 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002713 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002714
Johan Hedberg86742e12011-11-07 23:13:38 +02002715 expected_len = sizeof(*cp) + key_count *
2716 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002717 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002718 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002719 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002720 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2721 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002722 }
2723
Johan Hedberg4ae14302013-01-20 14:27:13 +02002724 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002725 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2726 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002727
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002728 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002729 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002730
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002731 for (i = 0; i < key_count; i++) {
2732 struct mgmt_link_key_info *key = &cp->keys[i];
2733
Marcel Holtmann8e991132014-01-10 02:07:25 -08002734 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002735 return mgmt_cmd_status(sk, hdev->id,
2736 MGMT_OP_LOAD_LINK_KEYS,
2737 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002738 }
2739
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002740 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002741
2742 hci_link_keys_clear(hdev);
2743
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002744 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002745 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002746 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002747 changed = hci_dev_test_and_clear_flag(hdev,
2748 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002749
2750 if (changed)
2751 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002752
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002753 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002754 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002755
Johan Hedberg58e92932014-06-24 14:00:26 +03002756 /* Always ignore debug keys and require a new pairing if
2757 * the user wants to use them.
2758 */
2759 if (key->type == HCI_LK_DEBUG_COMBINATION)
2760 continue;
2761
Johan Hedberg7652ff62014-06-24 13:15:49 +03002762 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2763 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002764 }
2765
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002766 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002767
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002768 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002769
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002770 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002771}
2772
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002773static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002774 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002775{
2776 struct mgmt_ev_device_unpaired ev;
2777
2778 bacpy(&ev.addr.bdaddr, bdaddr);
2779 ev.addr.type = addr_type;
2780
2781 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002782 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002783}
2784
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002785static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002786 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002787{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002788 struct mgmt_cp_unpair_device *cp = data;
2789 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002790 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002791 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002792 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002793 int err;
2794
Johan Hedberga8a1d192011-11-10 15:54:38 +02002795 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002796 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2797 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002798
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002799 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002800 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2801 MGMT_STATUS_INVALID_PARAMS,
2802 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002803
Johan Hedberg118da702013-01-20 14:27:20 +02002804 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002805 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2806 MGMT_STATUS_INVALID_PARAMS,
2807 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002808
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002809 hci_dev_lock(hdev);
2810
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002811 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002812 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2813 MGMT_STATUS_NOT_POWERED, &rp,
2814 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002815 goto unlock;
2816 }
2817
Johan Hedberge0b2b272014-02-18 17:14:31 +02002818 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002819 /* If disconnection is requested, then look up the
2820 * connection. If the remote device is connected, it
2821 * will be later used to terminate the link.
2822 *
2823 * Setting it to NULL explicitly will cause no
2824 * termination of the link.
2825 */
2826 if (cp->disconnect)
2827 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2828 &cp->addr.bdaddr);
2829 else
2830 conn = NULL;
2831
Johan Hedberg124f6e32012-02-09 13:50:12 +02002832 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002833 } else {
2834 u8 addr_type;
2835
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002836 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2837 &cp->addr.bdaddr);
2838 if (conn) {
2839 /* Defer clearing up the connection parameters
2840 * until closing to give a chance of keeping
2841 * them if a repairing happens.
2842 */
2843 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2844
2845 /* If disconnection is not requested, then
2846 * clear the connection variable so that the
2847 * link is not terminated.
2848 */
2849 if (!cp->disconnect)
2850 conn = NULL;
2851 }
2852
Johan Hedberge0b2b272014-02-18 17:14:31 +02002853 if (cp->addr.type == BDADDR_LE_PUBLIC)
2854 addr_type = ADDR_LE_DEV_PUBLIC;
2855 else
2856 addr_type = ADDR_LE_DEV_RANDOM;
2857
Johan Hedberga7ec7332014-02-18 17:14:35 +02002858 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2859
Johan Hedberge0b2b272014-02-18 17:14:31 +02002860 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2861 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002862
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002863 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002864 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2865 MGMT_STATUS_NOT_PAIRED, &rp,
2866 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002867 goto unlock;
2868 }
2869
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002870 /* If the connection variable is set, then termination of the
2871 * link is requested.
2872 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002873 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002874 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2875 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002876 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002877 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002878 }
2879
Johan Hedberg124f6e32012-02-09 13:50:12 +02002880 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002881 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002882 if (!cmd) {
2883 err = -ENOMEM;
2884 goto unlock;
2885 }
2886
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002887 cmd->cmd_complete = addr_cmd_complete;
2888
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002889 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002890 dc.reason = 0x13; /* Remote User Terminated Connection */
2891 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2892 if (err < 0)
2893 mgmt_pending_remove(cmd);
2894
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002895unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002896 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002897 return err;
2898}
2899
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002900static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002901 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002902{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002903 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002904 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002905 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002906 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002907 int err;
2908
2909 BT_DBG("");
2910
Johan Hedberg06a63b12013-01-20 14:27:21 +02002911 memset(&rp, 0, sizeof(rp));
2912 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2913 rp.addr.type = cp->addr.type;
2914
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002915 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002916 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2917 MGMT_STATUS_INVALID_PARAMS,
2918 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002919
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002920 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002921
2922 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002923 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2924 MGMT_STATUS_NOT_POWERED, &rp,
2925 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002926 goto failed;
2927 }
2928
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002929 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002930 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2931 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002932 goto failed;
2933 }
2934
Andre Guedes591f47f2012-04-24 21:02:49 -03002935 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002936 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2937 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002938 else
2939 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002940
Vishal Agarwalf9607272012-06-13 05:32:43 +05302941 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002942 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2943 MGMT_STATUS_NOT_CONNECTED, &rp,
2944 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002945 goto failed;
2946 }
2947
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002948 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002949 if (!cmd) {
2950 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002951 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002952 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002953
Johan Hedbergf5818c22014-12-05 13:36:02 +02002954 cmd->cmd_complete = generic_cmd_complete;
2955
Johan Hedberge3f2f922014-08-18 20:33:33 +03002956 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002957 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002958 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002959
2960failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002961 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002962 return err;
2963}
2964
Andre Guedes57c14772012-04-24 21:02:50 -03002965static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002966{
2967 switch (link_type) {
2968 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002969 switch (addr_type) {
2970 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002971 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002972
Johan Hedberg48264f02011-11-09 13:58:58 +02002973 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002974 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002975 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002976 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002977
Johan Hedberg4c659c32011-11-07 23:13:39 +02002978 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002979 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002980 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002981 }
2982}
2983
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002984static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2985 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002986{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002987 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002988 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002989 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002990 int err;
2991 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002992
2993 BT_DBG("");
2994
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002995 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002996
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002997 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002998 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2999 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003000 goto unlock;
3001 }
3002
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003003 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003004 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3005 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003006 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003007 }
3008
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003009 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003010 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003011 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003012 err = -ENOMEM;
3013 goto unlock;
3014 }
3015
Johan Hedberg2784eb42011-01-21 13:56:35 +02003016 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003017 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003018 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3019 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003020 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003021 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003022 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003023 continue;
3024 i++;
3025 }
3026
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003027 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003028
Johan Hedberg4c659c32011-11-07 23:13:39 +02003029 /* Recalculate length in case of filtered SCO connections, etc */
3030 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003031
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003032 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3033 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003034
Johan Hedberga38528f2011-01-22 06:46:43 +02003035 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003036
3037unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003038 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003039 return err;
3040}
3041
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003042static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003043 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003044{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003045 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003046 int err;
3047
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003048 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003049 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003050 if (!cmd)
3051 return -ENOMEM;
3052
Johan Hedbergd8457692012-02-17 14:24:57 +02003053 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003054 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003055 if (err < 0)
3056 mgmt_pending_remove(cmd);
3057
3058 return err;
3059}
3060
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003061static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003062 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003063{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003064 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003065 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003066 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003067 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003068 int err;
3069
3070 BT_DBG("");
3071
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003072 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003073
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003074 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003075 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3076 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003077 goto failed;
3078 }
3079
Johan Hedbergd8457692012-02-17 14:24:57 +02003080 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003081 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003082 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3083 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003084 goto failed;
3085 }
3086
3087 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003088 struct mgmt_cp_pin_code_neg_reply ncp;
3089
3090 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003091
3092 BT_ERR("PIN code is not 16 bytes long");
3093
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003094 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003095 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003096 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3097 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003098
3099 goto failed;
3100 }
3101
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003102 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003103 if (!cmd) {
3104 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003105 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003106 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003107
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003108 cmd->cmd_complete = addr_cmd_complete;
3109
Johan Hedbergd8457692012-02-17 14:24:57 +02003110 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003111 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003112 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003113
3114 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3115 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003116 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003117
3118failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003119 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003120 return err;
3121}
3122
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003123static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3124 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003125{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003126 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003127
3128 BT_DBG("");
3129
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003130 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003131 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3132 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003133
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003134 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003135
3136 hdev->io_capability = cp->io_capability;
3137
3138 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003139 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003140
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003141 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003142
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003143 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3144 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003145}
3146
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003147static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003148{
3149 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003150 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003152 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003153 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3154 continue;
3155
Johan Hedberge9a416b2011-02-19 12:05:56 -03003156 if (cmd->user_data != conn)
3157 continue;
3158
3159 return cmd;
3160 }
3161
3162 return NULL;
3163}
3164
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003165static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003166{
3167 struct mgmt_rp_pair_device rp;
3168 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003169 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003170
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003171 bacpy(&rp.addr.bdaddr, &conn->dst);
3172 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003173
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003174 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3175 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003176
3177 /* So we don't get further callbacks for this connection */
3178 conn->connect_cfm_cb = NULL;
3179 conn->security_cfm_cb = NULL;
3180 conn->disconn_cfm_cb = NULL;
3181
David Herrmann76a68ba2013-04-06 20:28:37 +02003182 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003183
3184 /* The device is paired so there is no need to remove
3185 * its connection parameters anymore.
3186 */
3187 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003188
3189 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003190
3191 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003192}
3193
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003194void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3195{
3196 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003197 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003198
3199 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003200 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003201 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003202 mgmt_pending_remove(cmd);
3203 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003204}
3205
Johan Hedberge9a416b2011-02-19 12:05:56 -03003206static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3207{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003208 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003209
3210 BT_DBG("status %u", status);
3211
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003212 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003213 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003214 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003215 return;
3216 }
3217
3218 cmd->cmd_complete(cmd, mgmt_status(status));
3219 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003220}
3221
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003222static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303223{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003224 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303225
3226 BT_DBG("status %u", status);
3227
3228 if (!status)
3229 return;
3230
3231 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003232 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303233 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003234 return;
3235 }
3236
3237 cmd->cmd_complete(cmd, mgmt_status(status));
3238 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303239}
3240
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003241static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003242 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003244 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003245 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003246 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003247 u8 sec_level, auth_type;
3248 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003249 int err;
3250
3251 BT_DBG("");
3252
Szymon Jancf950a30e2013-01-18 12:48:07 +01003253 memset(&rp, 0, sizeof(rp));
3254 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3255 rp.addr.type = cp->addr.type;
3256
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003257 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003258 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3259 MGMT_STATUS_INVALID_PARAMS,
3260 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003261
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003262 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003263 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3264 MGMT_STATUS_INVALID_PARAMS,
3265 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003266
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003267 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003268
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003269 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003270 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3271 MGMT_STATUS_NOT_POWERED, &rp,
3272 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003273 goto unlock;
3274 }
3275
Johan Hedberg55e76b32015-03-10 22:34:40 +02003276 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3277 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3278 MGMT_STATUS_ALREADY_PAIRED, &rp,
3279 sizeof(rp));
3280 goto unlock;
3281 }
3282
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003283 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003284 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003285
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003286 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003287 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3288 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003289 } else {
3290 u8 addr_type;
3291
3292 /* Convert from L2CAP channel address type to HCI address type
3293 */
3294 if (cp->addr.type == BDADDR_LE_PUBLIC)
3295 addr_type = ADDR_LE_DEV_PUBLIC;
3296 else
3297 addr_type = ADDR_LE_DEV_RANDOM;
3298
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003299 /* When pairing a new device, it is expected to remember
3300 * this device for future connections. Adding the connection
3301 * parameter information ahead of time allows tracking
3302 * of the slave preferred values and will speed up any
3303 * further connection establishment.
3304 *
3305 * If connection parameters already exist, then they
3306 * will be kept and this function does nothing.
3307 */
3308 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3309
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003310 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003311 sec_level, HCI_LE_CONN_TIMEOUT,
3312 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003313 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003314
Ville Tervo30e76272011-02-22 16:10:53 -03003315 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003316 int status;
3317
3318 if (PTR_ERR(conn) == -EBUSY)
3319 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003320 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3321 status = MGMT_STATUS_NOT_SUPPORTED;
3322 else if (PTR_ERR(conn) == -ECONNREFUSED)
3323 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003324 else
3325 status = MGMT_STATUS_CONNECT_FAILED;
3326
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003327 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3328 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003329 goto unlock;
3330 }
3331
3332 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003333 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003334 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3335 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003336 goto unlock;
3337 }
3338
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003339 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003340 if (!cmd) {
3341 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003342 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003343 goto unlock;
3344 }
3345
Johan Hedberg04ab2742014-12-05 13:36:04 +02003346 cmd->cmd_complete = pairing_complete;
3347
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003348 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003349 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003350 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003351 conn->security_cfm_cb = pairing_complete_cb;
3352 conn->disconn_cfm_cb = pairing_complete_cb;
3353 } else {
3354 conn->connect_cfm_cb = le_pairing_complete_cb;
3355 conn->security_cfm_cb = le_pairing_complete_cb;
3356 conn->disconn_cfm_cb = le_pairing_complete_cb;
3357 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003358
Johan Hedberge9a416b2011-02-19 12:05:56 -03003359 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003360 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003361
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003362 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003363 hci_conn_security(conn, sec_level, auth_type, true)) {
3364 cmd->cmd_complete(cmd, 0);
3365 mgmt_pending_remove(cmd);
3366 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003367
3368 err = 0;
3369
3370unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003371 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003372 return err;
3373}
3374
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003375static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3376 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003377{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003378 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003379 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003380 struct hci_conn *conn;
3381 int err;
3382
3383 BT_DBG("");
3384
Johan Hedberg28424702012-02-02 04:02:29 +02003385 hci_dev_lock(hdev);
3386
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003387 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003388 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3389 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003390 goto unlock;
3391 }
3392
Johan Hedberg28424702012-02-02 04:02:29 +02003393 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3394 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003395 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3396 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003397 goto unlock;
3398 }
3399
3400 conn = cmd->user_data;
3401
3402 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003403 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3404 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003405 goto unlock;
3406 }
3407
Johan Hedberga511b352014-12-11 21:45:45 +02003408 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3409 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003410
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003411 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3412 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003413unlock:
3414 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003415 return err;
3416}
3417
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003418static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003419 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003420 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003421{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003422 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003423 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003424 int err;
3425
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003426 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003427
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003428 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003429 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3430 MGMT_STATUS_NOT_POWERED, addr,
3431 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003432 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003433 }
3434
Johan Hedberg1707c602013-03-15 17:07:15 -05003435 if (addr->type == BDADDR_BREDR)
3436 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003437 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003438 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003439
Johan Hedberg272d90d2012-02-09 15:26:12 +02003440 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003441 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3442 MGMT_STATUS_NOT_CONNECTED, addr,
3443 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003444 goto done;
3445 }
3446
Johan Hedberg1707c602013-03-15 17:07:15 -05003447 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003448 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003449 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003450 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3451 MGMT_STATUS_SUCCESS, addr,
3452 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003453 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003454 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3455 MGMT_STATUS_FAILED, addr,
3456 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003457
Brian Gix47c15e22011-11-16 13:53:14 -08003458 goto done;
3459 }
3460
Johan Hedberg1707c602013-03-15 17:07:15 -05003461 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003462 if (!cmd) {
3463 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003464 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003465 }
3466
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003467 cmd->cmd_complete = addr_cmd_complete;
3468
Brian Gix0df4c182011-11-16 13:53:13 -08003469 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003470 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3471 struct hci_cp_user_passkey_reply cp;
3472
Johan Hedberg1707c602013-03-15 17:07:15 -05003473 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003474 cp.passkey = passkey;
3475 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3476 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003477 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3478 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003479
Johan Hedberga664b5b2011-02-19 12:06:02 -03003480 if (err < 0)
3481 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003482
Brian Gix0df4c182011-11-16 13:53:13 -08003483done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003484 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003485 return err;
3486}
3487
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303488static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3489 void *data, u16 len)
3490{
3491 struct mgmt_cp_pin_code_neg_reply *cp = data;
3492
3493 BT_DBG("");
3494
Johan Hedberg1707c602013-03-15 17:07:15 -05003495 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303496 MGMT_OP_PIN_CODE_NEG_REPLY,
3497 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3498}
3499
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003500static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3501 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003502{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003503 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003504
3505 BT_DBG("");
3506
3507 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003508 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3509 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003510
Johan Hedberg1707c602013-03-15 17:07:15 -05003511 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003512 MGMT_OP_USER_CONFIRM_REPLY,
3513 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003514}
3515
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003516static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003517 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003518{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003519 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003520
3521 BT_DBG("");
3522
Johan Hedberg1707c602013-03-15 17:07:15 -05003523 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003524 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3525 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003526}
3527
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003528static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3529 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003530{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003531 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003532
3533 BT_DBG("");
3534
Johan Hedberg1707c602013-03-15 17:07:15 -05003535 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003536 MGMT_OP_USER_PASSKEY_REPLY,
3537 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003538}
3539
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003540static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003541 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003542{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003543 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003544
3545 BT_DBG("");
3546
Johan Hedberg1707c602013-03-15 17:07:15 -05003547 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003548 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3549 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003550}
3551
Johan Hedberg13928972013-03-15 17:07:00 -05003552static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003553{
Johan Hedberg13928972013-03-15 17:07:00 -05003554 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003555 struct hci_cp_write_local_name cp;
3556
Johan Hedberg13928972013-03-15 17:07:00 -05003557 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003558
Johan Hedberg890ea892013-03-15 17:06:52 -05003559 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003560}
3561
Marcel Holtmann1904a852015-01-11 13:50:44 -08003562static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003563{
3564 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003565 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003566
3567 BT_DBG("status 0x%02x", status);
3568
3569 hci_dev_lock(hdev);
3570
3571 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3572 if (!cmd)
3573 goto unlock;
3574
3575 cp = cmd->param;
3576
3577 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003578 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3579 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003580 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003581 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3582 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003583
3584 mgmt_pending_remove(cmd);
3585
3586unlock:
3587 hci_dev_unlock(hdev);
3588}
3589
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003590static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003591 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003592{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003593 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003594 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003595 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003596 int err;
3597
3598 BT_DBG("");
3599
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003600 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003601
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003602 /* If the old values are the same as the new ones just return a
3603 * direct command complete event.
3604 */
3605 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3606 !memcmp(hdev->short_name, cp->short_name,
3607 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003608 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3609 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003610 goto failed;
3611 }
3612
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003613 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003614
Johan Hedbergb5235a62012-02-21 14:32:24 +02003615 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003616 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003617
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003618 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3619 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003620 if (err < 0)
3621 goto failed;
3622
3623 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003624 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003625
Johan Hedbergb5235a62012-02-21 14:32:24 +02003626 goto failed;
3627 }
3628
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003629 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003630 if (!cmd) {
3631 err = -ENOMEM;
3632 goto failed;
3633 }
3634
Johan Hedberg13928972013-03-15 17:07:00 -05003635 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3636
Johan Hedberg890ea892013-03-15 17:06:52 -05003637 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003638
3639 if (lmp_bredr_capable(hdev)) {
3640 update_name(&req);
3641 update_eir(&req);
3642 }
3643
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003644 /* The name is stored in the scan response data and so
3645 * no need to udpate the advertising data here.
3646 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003647 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003648 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003649
Johan Hedberg13928972013-03-15 17:07:00 -05003650 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003651 if (err < 0)
3652 mgmt_pending_remove(cmd);
3653
3654failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003655 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003656 return err;
3657}
3658
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003659static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003660 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003661{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003662 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003663 int err;
3664
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003665 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003666
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003667 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003668
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003669 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003670 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3671 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003672 goto unlock;
3673 }
3674
Andre Guedes9a1a1992012-07-24 15:03:48 -03003675 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003676 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3677 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003678 goto unlock;
3679 }
3680
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003681 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003682 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3683 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003684 goto unlock;
3685 }
3686
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003687 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003688 if (!cmd) {
3689 err = -ENOMEM;
3690 goto unlock;
3691 }
3692
Johan Hedberg710f11c2014-05-26 11:21:22 +03003693 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003694 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3695 0, NULL);
3696 else
3697 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3698
Szymon Jancc35938b2011-03-22 13:12:21 +01003699 if (err < 0)
3700 mgmt_pending_remove(cmd);
3701
3702unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003703 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003704 return err;
3705}
3706
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003707static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003708 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003709{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003710 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003711 int err;
3712
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003713 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003714
Johan Hedberg5d57e792015-01-23 10:10:38 +02003715 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003716 return mgmt_cmd_complete(sk, hdev->id,
3717 MGMT_OP_ADD_REMOTE_OOB_DATA,
3718 MGMT_STATUS_INVALID_PARAMS,
3719 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003720
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003721 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003722
Marcel Holtmannec109112014-01-10 02:07:30 -08003723 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3724 struct mgmt_cp_add_remote_oob_data *cp = data;
3725 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003726
Johan Hedbergc19a4952014-11-17 20:52:19 +02003727 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003728 err = mgmt_cmd_complete(sk, hdev->id,
3729 MGMT_OP_ADD_REMOTE_OOB_DATA,
3730 MGMT_STATUS_INVALID_PARAMS,
3731 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003732 goto unlock;
3733 }
3734
Marcel Holtmannec109112014-01-10 02:07:30 -08003735 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003736 cp->addr.type, cp->hash,
3737 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003738 if (err < 0)
3739 status = MGMT_STATUS_FAILED;
3740 else
3741 status = MGMT_STATUS_SUCCESS;
3742
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003743 err = mgmt_cmd_complete(sk, hdev->id,
3744 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3745 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003746 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3747 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003748 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003749 u8 status;
3750
Johan Hedberg86df9202014-10-26 20:52:27 +01003751 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003752 /* Enforce zero-valued 192-bit parameters as
3753 * long as legacy SMP OOB isn't implemented.
3754 */
3755 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3756 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003757 err = mgmt_cmd_complete(sk, hdev->id,
3758 MGMT_OP_ADD_REMOTE_OOB_DATA,
3759 MGMT_STATUS_INVALID_PARAMS,
3760 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003761 goto unlock;
3762 }
3763
Johan Hedberg86df9202014-10-26 20:52:27 +01003764 rand192 = NULL;
3765 hash192 = NULL;
3766 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003767 /* In case one of the P-192 values is set to zero,
3768 * then just disable OOB data for P-192.
3769 */
3770 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3771 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3772 rand192 = NULL;
3773 hash192 = NULL;
3774 } else {
3775 rand192 = cp->rand192;
3776 hash192 = cp->hash192;
3777 }
3778 }
3779
3780 /* In case one of the P-256 values is set to zero, then just
3781 * disable OOB data for P-256.
3782 */
3783 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3784 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3785 rand256 = NULL;
3786 hash256 = NULL;
3787 } else {
3788 rand256 = cp->rand256;
3789 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003790 }
3791
Johan Hedberg81328d52014-10-26 20:33:47 +01003792 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003793 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003794 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003795 if (err < 0)
3796 status = MGMT_STATUS_FAILED;
3797 else
3798 status = MGMT_STATUS_SUCCESS;
3799
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003800 err = mgmt_cmd_complete(sk, hdev->id,
3801 MGMT_OP_ADD_REMOTE_OOB_DATA,
3802 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003803 } else {
3804 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003805 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3806 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003807 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003808
Johan Hedbergc19a4952014-11-17 20:52:19 +02003809unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003810 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003811 return err;
3812}
3813
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003814static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003815 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003816{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003817 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003818 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003819 int err;
3820
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003821 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003822
Johan Hedbergc19a4952014-11-17 20:52:19 +02003823 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003824 return mgmt_cmd_complete(sk, hdev->id,
3825 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3826 MGMT_STATUS_INVALID_PARAMS,
3827 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003828
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003829 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003830
Johan Hedbergeedbd582014-11-15 09:34:23 +02003831 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3832 hci_remote_oob_data_clear(hdev);
3833 status = MGMT_STATUS_SUCCESS;
3834 goto done;
3835 }
3836
Johan Hedberg6928a922014-10-26 20:46:09 +01003837 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003838 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003839 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003840 else
Szymon Janca6785be2012-12-13 15:11:21 +01003841 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003842
Johan Hedbergeedbd582014-11-15 09:34:23 +02003843done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003844 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3845 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003846
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003847 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003848 return err;
3849}
3850
Marcel Holtmann80190442014-12-04 11:36:36 +01003851static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003852{
Marcel Holtmann80190442014-12-04 11:36:36 +01003853 struct hci_dev *hdev = req->hdev;
3854 struct hci_cp_le_set_scan_param param_cp;
3855 struct hci_cp_le_set_scan_enable enable_cp;
3856 struct hci_cp_inquiry inq_cp;
3857 /* General inquiry access code (GIAC) */
3858 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3859 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003860 int err;
3861
Marcel Holtmann80190442014-12-04 11:36:36 +01003862 switch (hdev->discovery.type) {
3863 case DISCOV_TYPE_BREDR:
3864 *status = mgmt_bredr_support(hdev);
3865 if (*status)
3866 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003867
Marcel Holtmann80190442014-12-04 11:36:36 +01003868 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3869 *status = MGMT_STATUS_BUSY;
3870 return false;
3871 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003872
Marcel Holtmann80190442014-12-04 11:36:36 +01003873 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003874
Marcel Holtmann80190442014-12-04 11:36:36 +01003875 memset(&inq_cp, 0, sizeof(inq_cp));
3876 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3877 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3878 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3879 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003880
Marcel Holtmann80190442014-12-04 11:36:36 +01003881 case DISCOV_TYPE_LE:
3882 case DISCOV_TYPE_INTERLEAVED:
3883 *status = mgmt_le_support(hdev);
3884 if (*status)
3885 return false;
3886
3887 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003888 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003889 *status = MGMT_STATUS_NOT_SUPPORTED;
3890 return false;
3891 }
3892
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003893 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003894 /* Don't let discovery abort an outgoing
3895 * connection attempt that's using directed
3896 * advertising.
3897 */
3898 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3899 BT_CONNECT)) {
3900 *status = MGMT_STATUS_REJECTED;
3901 return false;
3902 }
3903
3904 disable_advertising(req);
3905 }
3906
3907 /* If controller is scanning, it means the background scanning
3908 * is running. Thus, we should temporarily stop it in order to
3909 * set the discovery scanning parameters.
3910 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003911 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003912 hci_req_add_le_scan_disable(req);
3913
3914 memset(&param_cp, 0, sizeof(param_cp));
3915
3916 /* All active scans will be done with either a resolvable
3917 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003918 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003919 */
3920 err = hci_update_random_address(req, true, &own_addr_type);
3921 if (err < 0) {
3922 *status = MGMT_STATUS_FAILED;
3923 return false;
3924 }
3925
3926 param_cp.type = LE_SCAN_ACTIVE;
3927 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3928 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3929 param_cp.own_address_type = own_addr_type;
3930 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3931 &param_cp);
3932
3933 memset(&enable_cp, 0, sizeof(enable_cp));
3934 enable_cp.enable = LE_SCAN_ENABLE;
3935 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3936 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3937 &enable_cp);
3938 break;
3939
3940 default:
3941 *status = MGMT_STATUS_INVALID_PARAMS;
3942 return false;
3943 }
3944
3945 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003946}
3947
Marcel Holtmann1904a852015-01-11 13:50:44 -08003948static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3949 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003950{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003951 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003952 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003953
Andre Guedes7c307722013-04-30 15:29:28 -03003954 BT_DBG("status %d", status);
3955
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003956 hci_dev_lock(hdev);
3957
3958 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003959 if (!cmd)
3960 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3961
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003962 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003963 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003964 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003965 }
3966
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003967 if (status) {
3968 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3969 goto unlock;
3970 }
3971
Andre Guedes7c307722013-04-30 15:29:28 -03003972 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003973
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003974 /* If the scan involves LE scan, pick proper timeout to schedule
3975 * hdev->le_scan_disable that will stop it.
3976 */
Andre Guedes7c307722013-04-30 15:29:28 -03003977 switch (hdev->discovery.type) {
3978 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003979 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003980 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003981 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003982 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003983 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003984 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003985 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003986 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003987 default:
3988 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003989 timeout = 0;
3990 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003991 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003992
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003993 if (timeout) {
3994 /* When service discovery is used and the controller has
3995 * a strict duplicate filter, it is important to remember
3996 * the start and duration of the scan. This is required
3997 * for restarting scanning during the discovery phase.
3998 */
3999 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4000 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004001 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004002 hdev->discovery.scan_start = jiffies;
4003 hdev->discovery.scan_duration = timeout;
4004 }
4005
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004006 queue_delayed_work(hdev->workqueue,
4007 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004008 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004009
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004010unlock:
4011 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004012}
4013
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004014static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004015 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004016{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004017 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004018 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004019 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004020 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004021 int err;
4022
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004023 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004024
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004025 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004026
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004027 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004028 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4029 MGMT_STATUS_NOT_POWERED,
4030 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004031 goto failed;
4032 }
4033
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004034 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004035 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004036 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4037 MGMT_STATUS_BUSY, &cp->type,
4038 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004039 goto failed;
4040 }
4041
Johan Hedberg2922a942014-12-05 13:36:06 +02004042 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004043 if (!cmd) {
4044 err = -ENOMEM;
4045 goto failed;
4046 }
4047
Johan Hedberg2922a942014-12-05 13:36:06 +02004048 cmd->cmd_complete = generic_cmd_complete;
4049
Marcel Holtmann22078802014-12-05 11:45:22 +01004050 /* Clear the discovery filter first to free any previously
4051 * allocated memory for the UUID list.
4052 */
4053 hci_discovery_filter_clear(hdev);
4054
Andre Guedes4aab14e2012-02-17 20:39:36 -03004055 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004056 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004057
Andre Guedes7c307722013-04-30 15:29:28 -03004058 hci_req_init(&req, hdev);
4059
Marcel Holtmann80190442014-12-04 11:36:36 +01004060 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004061 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4062 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004063 mgmt_pending_remove(cmd);
4064 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004065 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004066
Andre Guedes7c307722013-04-30 15:29:28 -03004067 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004068 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004069 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004070 goto failed;
4071 }
4072
4073 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004074
4075failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004076 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004077 return err;
4078}
4079
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004080static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4081 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004082{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004083 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4084 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004085}
4086
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004087static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4088 void *data, u16 len)
4089{
4090 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004091 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004092 struct hci_request req;
4093 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4094 u16 uuid_count, expected_len;
4095 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004096 int err;
4097
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004098 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004099
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004100 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004101
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004102 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004103 err = mgmt_cmd_complete(sk, hdev->id,
4104 MGMT_OP_START_SERVICE_DISCOVERY,
4105 MGMT_STATUS_NOT_POWERED,
4106 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004107 goto failed;
4108 }
4109
4110 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004111 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004112 err = mgmt_cmd_complete(sk, hdev->id,
4113 MGMT_OP_START_SERVICE_DISCOVERY,
4114 MGMT_STATUS_BUSY, &cp->type,
4115 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004116 goto failed;
4117 }
4118
4119 uuid_count = __le16_to_cpu(cp->uuid_count);
4120 if (uuid_count > max_uuid_count) {
4121 BT_ERR("service_discovery: too big uuid_count value %u",
4122 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004123 err = mgmt_cmd_complete(sk, hdev->id,
4124 MGMT_OP_START_SERVICE_DISCOVERY,
4125 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4126 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004127 goto failed;
4128 }
4129
4130 expected_len = sizeof(*cp) + uuid_count * 16;
4131 if (expected_len != len) {
4132 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4133 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004134 err = mgmt_cmd_complete(sk, hdev->id,
4135 MGMT_OP_START_SERVICE_DISCOVERY,
4136 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4137 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004138 goto failed;
4139 }
4140
4141 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004142 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004143 if (!cmd) {
4144 err = -ENOMEM;
4145 goto failed;
4146 }
4147
Johan Hedberg2922a942014-12-05 13:36:06 +02004148 cmd->cmd_complete = service_discovery_cmd_complete;
4149
Marcel Holtmann22078802014-12-05 11:45:22 +01004150 /* Clear the discovery filter first to free any previously
4151 * allocated memory for the UUID list.
4152 */
4153 hci_discovery_filter_clear(hdev);
4154
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004155 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004156 hdev->discovery.type = cp->type;
4157 hdev->discovery.rssi = cp->rssi;
4158 hdev->discovery.uuid_count = uuid_count;
4159
4160 if (uuid_count > 0) {
4161 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4162 GFP_KERNEL);
4163 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004164 err = mgmt_cmd_complete(sk, hdev->id,
4165 MGMT_OP_START_SERVICE_DISCOVERY,
4166 MGMT_STATUS_FAILED,
4167 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004168 mgmt_pending_remove(cmd);
4169 goto failed;
4170 }
4171 }
4172
4173 hci_req_init(&req, hdev);
4174
4175 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004176 err = mgmt_cmd_complete(sk, hdev->id,
4177 MGMT_OP_START_SERVICE_DISCOVERY,
4178 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004179 mgmt_pending_remove(cmd);
4180 goto failed;
4181 }
4182
4183 err = hci_req_run(&req, start_discovery_complete);
4184 if (err < 0) {
4185 mgmt_pending_remove(cmd);
4186 goto failed;
4187 }
4188
4189 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4190
4191failed:
4192 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004193 return err;
4194}
4195
Marcel Holtmann1904a852015-01-11 13:50:44 -08004196static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004197{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004198 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004199
Andre Guedes0e05bba2013-04-30 15:29:33 -03004200 BT_DBG("status %d", status);
4201
4202 hci_dev_lock(hdev);
4203
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004204 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4205 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004206 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004207 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004208 }
4209
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004210 if (!status)
4211 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004212
Andre Guedes0e05bba2013-04-30 15:29:33 -03004213 hci_dev_unlock(hdev);
4214}
4215
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004216static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004217 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004218{
Johan Hedbergd9306502012-02-20 23:25:18 +02004219 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004220 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004221 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004222 int err;
4223
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004224 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004225
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004226 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004227
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004228 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004229 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4230 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4231 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004232 goto unlock;
4233 }
4234
4235 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004236 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4237 MGMT_STATUS_INVALID_PARAMS,
4238 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004239 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004240 }
4241
Johan Hedberg2922a942014-12-05 13:36:06 +02004242 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004243 if (!cmd) {
4244 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004245 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004246 }
4247
Johan Hedberg2922a942014-12-05 13:36:06 +02004248 cmd->cmd_complete = generic_cmd_complete;
4249
Andre Guedes0e05bba2013-04-30 15:29:33 -03004250 hci_req_init(&req, hdev);
4251
Johan Hedberg21a60d32014-06-10 14:05:58 +03004252 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004253
Johan Hedberg21a60d32014-06-10 14:05:58 +03004254 err = hci_req_run(&req, stop_discovery_complete);
4255 if (!err) {
4256 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004257 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004258 }
4259
Johan Hedberg21a60d32014-06-10 14:05:58 +03004260 mgmt_pending_remove(cmd);
4261
4262 /* If no HCI commands were sent we're done */
4263 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004264 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4265 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004266 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4267 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004268
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004269unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004270 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004271 return err;
4272}
4273
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004274static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004275 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004276{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004277 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004278 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004279 int err;
4280
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004281 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004282
Johan Hedberg561aafb2012-01-04 13:31:59 +02004283 hci_dev_lock(hdev);
4284
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004285 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004286 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4287 MGMT_STATUS_FAILED, &cp->addr,
4288 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004289 goto failed;
4290 }
4291
Johan Hedberga198e7b2012-02-17 14:27:06 +02004292 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004293 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004294 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4295 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4296 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004297 goto failed;
4298 }
4299
4300 if (cp->name_known) {
4301 e->name_state = NAME_KNOWN;
4302 list_del(&e->list);
4303 } else {
4304 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004305 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004306 }
4307
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004308 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4309 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004310
4311failed:
4312 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004313 return err;
4314}
4315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004316static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004317 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004318{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004319 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004320 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004321 int err;
4322
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004323 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004324
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004325 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004326 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4327 MGMT_STATUS_INVALID_PARAMS,
4328 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004329
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004330 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004331
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004332 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4333 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004334 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004335 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004336 goto done;
4337 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004338
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004339 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4340 sk);
4341 status = MGMT_STATUS_SUCCESS;
4342
4343done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004344 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4345 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004346
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004347 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004348
4349 return err;
4350}
4351
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004352static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004353 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004354{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004355 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004356 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004357 int err;
4358
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004359 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004360
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004361 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004362 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4363 MGMT_STATUS_INVALID_PARAMS,
4364 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004365
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004366 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004367
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004368 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4369 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004370 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004371 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004372 goto done;
4373 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004374
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004375 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4376 sk);
4377 status = MGMT_STATUS_SUCCESS;
4378
4379done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004380 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4381 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004382
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004383 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004384
4385 return err;
4386}
4387
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004388static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4389 u16 len)
4390{
4391 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004392 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004393 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004394 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004395
4396 BT_DBG("%s", hdev->name);
4397
Szymon Jancc72d4b82012-03-16 16:02:57 +01004398 source = __le16_to_cpu(cp->source);
4399
4400 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004401 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4402 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004403
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004404 hci_dev_lock(hdev);
4405
Szymon Jancc72d4b82012-03-16 16:02:57 +01004406 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004407 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4408 hdev->devid_product = __le16_to_cpu(cp->product);
4409 hdev->devid_version = __le16_to_cpu(cp->version);
4410
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004411 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4412 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004413
Johan Hedberg890ea892013-03-15 17:06:52 -05004414 hci_req_init(&req, hdev);
4415 update_eir(&req);
4416 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004417
4418 hci_dev_unlock(hdev);
4419
4420 return err;
4421}
4422
Marcel Holtmann1904a852015-01-11 13:50:44 -08004423static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4424 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004425{
4426 struct cmd_lookup match = { NULL, hdev };
4427
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304428 hci_dev_lock(hdev);
4429
Johan Hedberg4375f102013-09-25 13:26:10 +03004430 if (status) {
4431 u8 mgmt_err = mgmt_status(status);
4432
4433 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4434 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304435 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004436 }
4437
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004438 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004439 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004440 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004441 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004442
Johan Hedberg4375f102013-09-25 13:26:10 +03004443 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4444 &match);
4445
4446 new_settings(hdev, match.sk);
4447
4448 if (match.sk)
4449 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304450
4451unlock:
4452 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004453}
4454
Marcel Holtmann21b51872013-10-10 09:47:53 -07004455static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4456 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004457{
4458 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004459 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004460 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004461 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004462 int err;
4463
4464 BT_DBG("request for %s", hdev->name);
4465
Johan Hedberge6fe7982013-10-02 15:45:22 +03004466 status = mgmt_le_support(hdev);
4467 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004468 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4469 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004470
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004471 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004472 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4473 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004474
4475 hci_dev_lock(hdev);
4476
4477 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004478
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004479 /* The following conditions are ones which mean that we should
4480 * not do any HCI communication but directly send a mgmt
4481 * response to user space (after toggling the flag if
4482 * necessary).
4483 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004484 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004485 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4486 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004487 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004488 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004489 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004490 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004491
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004492 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004493 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004494 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004495 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004496 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004497 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004498 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004499 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004500 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004501 }
4502
4503 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4504 if (err < 0)
4505 goto unlock;
4506
4507 if (changed)
4508 err = new_settings(hdev, sk);
4509
4510 goto unlock;
4511 }
4512
4513 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4514 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004515 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4516 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004517 goto unlock;
4518 }
4519
4520 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4521 if (!cmd) {
4522 err = -ENOMEM;
4523 goto unlock;
4524 }
4525
4526 hci_req_init(&req, hdev);
4527
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004528 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004529 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004530 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004531 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004532
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004533 if (val)
4534 enable_advertising(&req);
4535 else
4536 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004537
4538 err = hci_req_run(&req, set_advertising_complete);
4539 if (err < 0)
4540 mgmt_pending_remove(cmd);
4541
4542unlock:
4543 hci_dev_unlock(hdev);
4544 return err;
4545}
4546
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004547static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4548 void *data, u16 len)
4549{
4550 struct mgmt_cp_set_static_address *cp = data;
4551 int err;
4552
4553 BT_DBG("%s", hdev->name);
4554
Marcel Holtmann62af4442013-10-02 22:10:32 -07004555 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004556 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4557 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004558
4559 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004560 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4561 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004562
4563 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4564 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004565 return mgmt_cmd_status(sk, hdev->id,
4566 MGMT_OP_SET_STATIC_ADDRESS,
4567 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004568
4569 /* Two most significant bits shall be set */
4570 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004571 return mgmt_cmd_status(sk, hdev->id,
4572 MGMT_OP_SET_STATIC_ADDRESS,
4573 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004574 }
4575
4576 hci_dev_lock(hdev);
4577
4578 bacpy(&hdev->static_addr, &cp->bdaddr);
4579
Marcel Holtmann93690c22015-03-06 10:11:21 -08004580 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4581 if (err < 0)
4582 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004583
Marcel Holtmann93690c22015-03-06 10:11:21 -08004584 err = new_settings(hdev, sk);
4585
4586unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004587 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004588 return err;
4589}
4590
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004591static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4592 void *data, u16 len)
4593{
4594 struct mgmt_cp_set_scan_params *cp = data;
4595 __u16 interval, window;
4596 int err;
4597
4598 BT_DBG("%s", hdev->name);
4599
4600 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004601 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4602 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004603
4604 interval = __le16_to_cpu(cp->interval);
4605
4606 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004607 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4608 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004609
4610 window = __le16_to_cpu(cp->window);
4611
4612 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004613 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4614 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004615
Marcel Holtmann899e1072013-10-14 09:55:32 -07004616 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004617 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4618 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004619
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004620 hci_dev_lock(hdev);
4621
4622 hdev->le_scan_interval = interval;
4623 hdev->le_scan_window = window;
4624
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004625 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4626 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004627
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004628 /* If background scan is running, restart it so new parameters are
4629 * loaded.
4630 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004631 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004632 hdev->discovery.state == DISCOVERY_STOPPED) {
4633 struct hci_request req;
4634
4635 hci_req_init(&req, hdev);
4636
4637 hci_req_add_le_scan_disable(&req);
4638 hci_req_add_le_passive_scan(&req);
4639
4640 hci_req_run(&req, NULL);
4641 }
4642
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004643 hci_dev_unlock(hdev);
4644
4645 return err;
4646}
4647
Marcel Holtmann1904a852015-01-11 13:50:44 -08004648static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4649 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004650{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004651 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004652
4653 BT_DBG("status 0x%02x", status);
4654
4655 hci_dev_lock(hdev);
4656
4657 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4658 if (!cmd)
4659 goto unlock;
4660
4661 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004662 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4663 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004664 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004665 struct mgmt_mode *cp = cmd->param;
4666
4667 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004668 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004669 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004670 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004671
Johan Hedberg33e38b32013-03-15 17:07:05 -05004672 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4673 new_settings(hdev, cmd->sk);
4674 }
4675
4676 mgmt_pending_remove(cmd);
4677
4678unlock:
4679 hci_dev_unlock(hdev);
4680}
4681
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004682static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004683 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004684{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004685 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004686 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004687 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004688 int err;
4689
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004690 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004691
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004692 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004693 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004694 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4695 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004696
Johan Hedberga7e80f22013-01-09 16:05:19 +02004697 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004698 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4699 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004700
Antti Julkuf6422ec2011-06-22 13:11:56 +03004701 hci_dev_lock(hdev);
4702
Johan Hedberg05cbf292013-03-15 17:07:07 -05004703 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004704 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4705 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004706 goto unlock;
4707 }
4708
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004709 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004710 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4711 hdev);
4712 goto unlock;
4713 }
4714
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004715 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004716 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004717 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4718 hdev);
4719 new_settings(hdev, sk);
4720 goto unlock;
4721 }
4722
Johan Hedberg33e38b32013-03-15 17:07:05 -05004723 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4724 data, len);
4725 if (!cmd) {
4726 err = -ENOMEM;
4727 goto unlock;
4728 }
4729
4730 hci_req_init(&req, hdev);
4731
Johan Hedberg406d7802013-03-15 17:07:09 -05004732 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004733
4734 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004735 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004736 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4737 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004738 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004739 }
4740
Johan Hedberg33e38b32013-03-15 17:07:05 -05004741unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004742 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004743
Antti Julkuf6422ec2011-06-22 13:11:56 +03004744 return err;
4745}
4746
Marcel Holtmann1904a852015-01-11 13:50:44 -08004747static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004748{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004749 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004750
4751 BT_DBG("status 0x%02x", status);
4752
4753 hci_dev_lock(hdev);
4754
4755 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4756 if (!cmd)
4757 goto unlock;
4758
4759 if (status) {
4760 u8 mgmt_err = mgmt_status(status);
4761
4762 /* We need to restore the flag if related HCI commands
4763 * failed.
4764 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004765 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004766
Johan Hedberga69e8372015-03-06 21:08:53 +02004767 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004768 } else {
4769 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4770 new_settings(hdev, cmd->sk);
4771 }
4772
4773 mgmt_pending_remove(cmd);
4774
4775unlock:
4776 hci_dev_unlock(hdev);
4777}
4778
4779static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4780{
4781 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004782 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004783 struct hci_request req;
4784 int err;
4785
4786 BT_DBG("request for %s", hdev->name);
4787
4788 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004789 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4790 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004791
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004792 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004793 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4794 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004795
4796 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004797 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4798 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004799
4800 hci_dev_lock(hdev);
4801
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004802 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004803 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4804 goto unlock;
4805 }
4806
4807 if (!hdev_is_powered(hdev)) {
4808 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004809 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4810 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4811 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4812 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4813 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004814 }
4815
Marcel Holtmannce05d602015-03-13 02:11:03 -07004816 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004817
4818 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4819 if (err < 0)
4820 goto unlock;
4821
4822 err = new_settings(hdev, sk);
4823 goto unlock;
4824 }
4825
4826 /* Reject disabling when powered on */
4827 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004828 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4829 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004830 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004831 } else {
4832 /* When configuring a dual-mode controller to operate
4833 * with LE only and using a static address, then switching
4834 * BR/EDR back on is not allowed.
4835 *
4836 * Dual-mode controllers shall operate with the public
4837 * address as its identity address for BR/EDR and LE. So
4838 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004839 *
4840 * The same restrictions applies when secure connections
4841 * has been enabled. For BR/EDR this is a controller feature
4842 * while for LE it is a host stack feature. This means that
4843 * switching BR/EDR back on when secure connections has been
4844 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004845 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004846 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004847 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004848 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004849 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4850 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004851 goto unlock;
4852 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004853 }
4854
4855 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004856 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4857 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004858 goto unlock;
4859 }
4860
4861 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4862 if (!cmd) {
4863 err = -ENOMEM;
4864 goto unlock;
4865 }
4866
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004867 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004868 * generates the correct flags.
4869 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004870 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004871
4872 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004873
Johan Hedberg432df052014-08-01 11:13:31 +03004874 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004875 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004876
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004877 /* Since only the advertising data flags will change, there
4878 * is no need to update the scan response data.
4879 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004880 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004881
Johan Hedberg0663ca22013-10-02 13:43:14 +03004882 err = hci_req_run(&req, set_bredr_complete);
4883 if (err < 0)
4884 mgmt_pending_remove(cmd);
4885
4886unlock:
4887 hci_dev_unlock(hdev);
4888 return err;
4889}
4890
Johan Hedberga1443f52015-01-23 15:42:46 +02004891static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4892{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004893 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004894 struct mgmt_mode *cp;
4895
4896 BT_DBG("%s status %u", hdev->name, status);
4897
4898 hci_dev_lock(hdev);
4899
4900 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4901 if (!cmd)
4902 goto unlock;
4903
4904 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004905 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4906 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004907 goto remove;
4908 }
4909
4910 cp = cmd->param;
4911
4912 switch (cp->val) {
4913 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004914 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
4915 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004916 break;
4917 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004918 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004919 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004920 break;
4921 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004922 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
4923 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004924 break;
4925 }
4926
4927 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4928 new_settings(hdev, cmd->sk);
4929
4930remove:
4931 mgmt_pending_remove(cmd);
4932unlock:
4933 hci_dev_unlock(hdev);
4934}
4935
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004936static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4937 void *data, u16 len)
4938{
4939 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004940 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004941 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004942 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004943 int err;
4944
4945 BT_DBG("request for %s", hdev->name);
4946
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004947 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004948 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004949 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4950 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004951
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004952 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004953 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004954 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004955 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4956 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004957
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004958 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004959 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004960 MGMT_STATUS_INVALID_PARAMS);
4961
4962 hci_dev_lock(hdev);
4963
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004964 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004965 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004966 bool changed;
4967
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004968 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004969 changed = !hci_dev_test_and_set_flag(hdev,
4970 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004971 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004972 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004973 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004974 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004975 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004976 changed = hci_dev_test_and_clear_flag(hdev,
4977 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004978 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004979 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004980
4981 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4982 if (err < 0)
4983 goto failed;
4984
4985 if (changed)
4986 err = new_settings(hdev, sk);
4987
4988 goto failed;
4989 }
4990
4991 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004992 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4993 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004994 goto failed;
4995 }
4996
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004997 val = !!cp->val;
4998
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004999 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5000 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005001 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5002 goto failed;
5003 }
5004
5005 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5006 if (!cmd) {
5007 err = -ENOMEM;
5008 goto failed;
5009 }
5010
Johan Hedberga1443f52015-01-23 15:42:46 +02005011 hci_req_init(&req, hdev);
5012 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5013 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005014 if (err < 0) {
5015 mgmt_pending_remove(cmd);
5016 goto failed;
5017 }
5018
5019failed:
5020 hci_dev_unlock(hdev);
5021 return err;
5022}
5023
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005024static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5025 void *data, u16 len)
5026{
5027 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005028 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005029 int err;
5030
5031 BT_DBG("request for %s", hdev->name);
5032
Johan Hedbergb97109792014-06-24 14:00:28 +03005033 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005034 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5035 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005036
5037 hci_dev_lock(hdev);
5038
5039 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005040 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005041 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005042 changed = hci_dev_test_and_clear_flag(hdev,
5043 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005044
Johan Hedbergb97109792014-06-24 14:00:28 +03005045 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005046 use_changed = !hci_dev_test_and_set_flag(hdev,
5047 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005048 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005049 use_changed = hci_dev_test_and_clear_flag(hdev,
5050 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005051
5052 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005053 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005054 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5055 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5056 sizeof(mode), &mode);
5057 }
5058
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005059 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5060 if (err < 0)
5061 goto unlock;
5062
5063 if (changed)
5064 err = new_settings(hdev, sk);
5065
5066unlock:
5067 hci_dev_unlock(hdev);
5068 return err;
5069}
5070
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005071static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5072 u16 len)
5073{
5074 struct mgmt_cp_set_privacy *cp = cp_data;
5075 bool changed;
5076 int err;
5077
5078 BT_DBG("request for %s", hdev->name);
5079
5080 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005081 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5082 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005083
5084 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005085 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5086 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005087
5088 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005089 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5090 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005091
5092 hci_dev_lock(hdev);
5093
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005094 /* If user space supports this command it is also expected to
5095 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5096 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005097 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005098
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005099 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005100 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005101 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005102 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005103 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005104 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005105 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005106 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005107 }
5108
5109 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5110 if (err < 0)
5111 goto unlock;
5112
5113 if (changed)
5114 err = new_settings(hdev, sk);
5115
5116unlock:
5117 hci_dev_unlock(hdev);
5118 return err;
5119}
5120
Johan Hedberg41edf162014-02-18 10:19:35 +02005121static bool irk_is_valid(struct mgmt_irk_info *irk)
5122{
5123 switch (irk->addr.type) {
5124 case BDADDR_LE_PUBLIC:
5125 return true;
5126
5127 case BDADDR_LE_RANDOM:
5128 /* Two most significant bits shall be set */
5129 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5130 return false;
5131 return true;
5132 }
5133
5134 return false;
5135}
5136
5137static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5138 u16 len)
5139{
5140 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005141 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5142 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005143 u16 irk_count, expected_len;
5144 int i, err;
5145
5146 BT_DBG("request for %s", hdev->name);
5147
5148 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005149 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5150 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005151
5152 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005153 if (irk_count > max_irk_count) {
5154 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005155 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5156 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005157 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005158
5159 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5160 if (expected_len != len) {
5161 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005162 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005163 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5164 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005165 }
5166
5167 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5168
5169 for (i = 0; i < irk_count; i++) {
5170 struct mgmt_irk_info *key = &cp->irks[i];
5171
5172 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005173 return mgmt_cmd_status(sk, hdev->id,
5174 MGMT_OP_LOAD_IRKS,
5175 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005176 }
5177
5178 hci_dev_lock(hdev);
5179
5180 hci_smp_irks_clear(hdev);
5181
5182 for (i = 0; i < irk_count; i++) {
5183 struct mgmt_irk_info *irk = &cp->irks[i];
5184 u8 addr_type;
5185
5186 if (irk->addr.type == BDADDR_LE_PUBLIC)
5187 addr_type = ADDR_LE_DEV_PUBLIC;
5188 else
5189 addr_type = ADDR_LE_DEV_RANDOM;
5190
5191 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5192 BDADDR_ANY);
5193 }
5194
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005195 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005196
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005197 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005198
5199 hci_dev_unlock(hdev);
5200
5201 return err;
5202}
5203
Johan Hedberg3f706b72013-01-20 14:27:16 +02005204static bool ltk_is_valid(struct mgmt_ltk_info *key)
5205{
5206 if (key->master != 0x00 && key->master != 0x01)
5207 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005208
5209 switch (key->addr.type) {
5210 case BDADDR_LE_PUBLIC:
5211 return true;
5212
5213 case BDADDR_LE_RANDOM:
5214 /* Two most significant bits shall be set */
5215 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5216 return false;
5217 return true;
5218 }
5219
5220 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005221}
5222
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005223static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005224 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005225{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005226 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005227 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5228 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005229 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005230 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005231
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005232 BT_DBG("request for %s", hdev->name);
5233
5234 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005235 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5236 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005237
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005238 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005239 if (key_count > max_key_count) {
5240 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005241 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5242 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005243 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005244
5245 expected_len = sizeof(*cp) + key_count *
5246 sizeof(struct mgmt_ltk_info);
5247 if (expected_len != len) {
5248 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005249 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005250 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5251 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005252 }
5253
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005254 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005255
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005256 for (i = 0; i < key_count; i++) {
5257 struct mgmt_ltk_info *key = &cp->keys[i];
5258
Johan Hedberg3f706b72013-01-20 14:27:16 +02005259 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005260 return mgmt_cmd_status(sk, hdev->id,
5261 MGMT_OP_LOAD_LONG_TERM_KEYS,
5262 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005263 }
5264
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005265 hci_dev_lock(hdev);
5266
5267 hci_smp_ltks_clear(hdev);
5268
5269 for (i = 0; i < key_count; i++) {
5270 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005271 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005272
5273 if (key->addr.type == BDADDR_LE_PUBLIC)
5274 addr_type = ADDR_LE_DEV_PUBLIC;
5275 else
5276 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005277
Johan Hedberg61b43352014-05-29 19:36:53 +03005278 switch (key->type) {
5279 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005280 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005281 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005282 break;
5283 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005284 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005285 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005286 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005287 case MGMT_LTK_P256_UNAUTH:
5288 authenticated = 0x00;
5289 type = SMP_LTK_P256;
5290 break;
5291 case MGMT_LTK_P256_AUTH:
5292 authenticated = 0x01;
5293 type = SMP_LTK_P256;
5294 break;
5295 case MGMT_LTK_P256_DEBUG:
5296 authenticated = 0x00;
5297 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005298 default:
5299 continue;
5300 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005301
Johan Hedberg35d70272014-02-19 14:57:47 +02005302 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005303 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005304 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005305 }
5306
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005307 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005308 NULL, 0);
5309
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005310 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005311
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005312 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005313}
5314
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005315static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005316{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005317 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005318 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005319 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005320
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005321 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005322
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005323 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005324 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005325 rp.tx_power = conn->tx_power;
5326 rp.max_tx_power = conn->max_tx_power;
5327 } else {
5328 rp.rssi = HCI_RSSI_INVALID;
5329 rp.tx_power = HCI_TX_POWER_INVALID;
5330 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005331 }
5332
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005333 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5334 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005335
5336 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005337 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005338
5339 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005340}
5341
Marcel Holtmann1904a852015-01-11 13:50:44 -08005342static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5343 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005344{
5345 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005346 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005347 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005348 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005349 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005350
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005351 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005352
5353 hci_dev_lock(hdev);
5354
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005355 /* Commands sent in request are either Read RSSI or Read Transmit Power
5356 * Level so we check which one was last sent to retrieve connection
5357 * handle. Both commands have handle as first parameter so it's safe to
5358 * cast data on the same command struct.
5359 *
5360 * First command sent is always Read RSSI and we fail only if it fails.
5361 * In other case we simply override error to indicate success as we
5362 * already remembered if TX power value is actually valid.
5363 */
5364 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5365 if (!cp) {
5366 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005367 status = MGMT_STATUS_SUCCESS;
5368 } else {
5369 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005370 }
5371
5372 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005373 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005374 goto unlock;
5375 }
5376
5377 handle = __le16_to_cpu(cp->handle);
5378 conn = hci_conn_hash_lookup_handle(hdev, handle);
5379 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005380 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005381 goto unlock;
5382 }
5383
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005384 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5385 if (!cmd)
5386 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005387
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005388 cmd->cmd_complete(cmd, status);
5389 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005390
5391unlock:
5392 hci_dev_unlock(hdev);
5393}
5394
5395static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5396 u16 len)
5397{
5398 struct mgmt_cp_get_conn_info *cp = data;
5399 struct mgmt_rp_get_conn_info rp;
5400 struct hci_conn *conn;
5401 unsigned long conn_info_age;
5402 int err = 0;
5403
5404 BT_DBG("%s", hdev->name);
5405
5406 memset(&rp, 0, sizeof(rp));
5407 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5408 rp.addr.type = cp->addr.type;
5409
5410 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005411 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5412 MGMT_STATUS_INVALID_PARAMS,
5413 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005414
5415 hci_dev_lock(hdev);
5416
5417 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005418 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5419 MGMT_STATUS_NOT_POWERED, &rp,
5420 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005421 goto unlock;
5422 }
5423
5424 if (cp->addr.type == BDADDR_BREDR)
5425 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5426 &cp->addr.bdaddr);
5427 else
5428 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5429
5430 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005431 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5432 MGMT_STATUS_NOT_CONNECTED, &rp,
5433 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005434 goto unlock;
5435 }
5436
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005437 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005438 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5439 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005440 goto unlock;
5441 }
5442
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005443 /* To avoid client trying to guess when to poll again for information we
5444 * calculate conn info age as random value between min/max set in hdev.
5445 */
5446 conn_info_age = hdev->conn_info_min_age +
5447 prandom_u32_max(hdev->conn_info_max_age -
5448 hdev->conn_info_min_age);
5449
5450 /* Query controller to refresh cached values if they are too old or were
5451 * never read.
5452 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005453 if (time_after(jiffies, conn->conn_info_timestamp +
5454 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005455 !conn->conn_info_timestamp) {
5456 struct hci_request req;
5457 struct hci_cp_read_tx_power req_txp_cp;
5458 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005459 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005460
5461 hci_req_init(&req, hdev);
5462 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5463 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5464 &req_rssi_cp);
5465
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005466 /* For LE links TX power does not change thus we don't need to
5467 * query for it once value is known.
5468 */
5469 if (!bdaddr_type_is_le(cp->addr.type) ||
5470 conn->tx_power == HCI_TX_POWER_INVALID) {
5471 req_txp_cp.handle = cpu_to_le16(conn->handle);
5472 req_txp_cp.type = 0x00;
5473 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5474 sizeof(req_txp_cp), &req_txp_cp);
5475 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005476
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005477 /* Max TX power needs to be read only once per connection */
5478 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5479 req_txp_cp.handle = cpu_to_le16(conn->handle);
5480 req_txp_cp.type = 0x01;
5481 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5482 sizeof(req_txp_cp), &req_txp_cp);
5483 }
5484
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005485 err = hci_req_run(&req, conn_info_refresh_complete);
5486 if (err < 0)
5487 goto unlock;
5488
5489 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5490 data, len);
5491 if (!cmd) {
5492 err = -ENOMEM;
5493 goto unlock;
5494 }
5495
5496 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005497 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005498 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005499
5500 conn->conn_info_timestamp = jiffies;
5501 } else {
5502 /* Cache is valid, just reply with values cached in hci_conn */
5503 rp.rssi = conn->rssi;
5504 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005505 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005506
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005507 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5508 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005509 }
5510
5511unlock:
5512 hci_dev_unlock(hdev);
5513 return err;
5514}
5515
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005516static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005517{
5518 struct hci_conn *conn = cmd->user_data;
5519 struct mgmt_rp_get_clock_info rp;
5520 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005521 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005522
5523 memset(&rp, 0, sizeof(rp));
5524 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5525
5526 if (status)
5527 goto complete;
5528
5529 hdev = hci_dev_get(cmd->index);
5530 if (hdev) {
5531 rp.local_clock = cpu_to_le32(hdev->clock);
5532 hci_dev_put(hdev);
5533 }
5534
5535 if (conn) {
5536 rp.piconet_clock = cpu_to_le32(conn->clock);
5537 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5538 }
5539
5540complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005541 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5542 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005543
5544 if (conn) {
5545 hci_conn_drop(conn);
5546 hci_conn_put(conn);
5547 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005548
5549 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005550}
5551
Marcel Holtmann1904a852015-01-11 13:50:44 -08005552static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005553{
Johan Hedberg95868422014-06-28 17:54:07 +03005554 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005555 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005556 struct hci_conn *conn;
5557
5558 BT_DBG("%s status %u", hdev->name, status);
5559
5560 hci_dev_lock(hdev);
5561
5562 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5563 if (!hci_cp)
5564 goto unlock;
5565
5566 if (hci_cp->which) {
5567 u16 handle = __le16_to_cpu(hci_cp->handle);
5568 conn = hci_conn_hash_lookup_handle(hdev, handle);
5569 } else {
5570 conn = NULL;
5571 }
5572
5573 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5574 if (!cmd)
5575 goto unlock;
5576
Johan Hedberg69487372014-12-05 13:36:07 +02005577 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005578 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005579
5580unlock:
5581 hci_dev_unlock(hdev);
5582}
5583
5584static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5585 u16 len)
5586{
5587 struct mgmt_cp_get_clock_info *cp = data;
5588 struct mgmt_rp_get_clock_info rp;
5589 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005590 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005591 struct hci_request req;
5592 struct hci_conn *conn;
5593 int err;
5594
5595 BT_DBG("%s", hdev->name);
5596
5597 memset(&rp, 0, sizeof(rp));
5598 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5599 rp.addr.type = cp->addr.type;
5600
5601 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005602 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5603 MGMT_STATUS_INVALID_PARAMS,
5604 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005605
5606 hci_dev_lock(hdev);
5607
5608 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005609 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5610 MGMT_STATUS_NOT_POWERED, &rp,
5611 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005612 goto unlock;
5613 }
5614
5615 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5616 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5617 &cp->addr.bdaddr);
5618 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005619 err = mgmt_cmd_complete(sk, hdev->id,
5620 MGMT_OP_GET_CLOCK_INFO,
5621 MGMT_STATUS_NOT_CONNECTED,
5622 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005623 goto unlock;
5624 }
5625 } else {
5626 conn = NULL;
5627 }
5628
5629 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5630 if (!cmd) {
5631 err = -ENOMEM;
5632 goto unlock;
5633 }
5634
Johan Hedberg69487372014-12-05 13:36:07 +02005635 cmd->cmd_complete = clock_info_cmd_complete;
5636
Johan Hedberg95868422014-06-28 17:54:07 +03005637 hci_req_init(&req, hdev);
5638
5639 memset(&hci_cp, 0, sizeof(hci_cp));
5640 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5641
5642 if (conn) {
5643 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005644 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005645
5646 hci_cp.handle = cpu_to_le16(conn->handle);
5647 hci_cp.which = 0x01; /* Piconet clock */
5648 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5649 }
5650
5651 err = hci_req_run(&req, get_clock_info_complete);
5652 if (err < 0)
5653 mgmt_pending_remove(cmd);
5654
5655unlock:
5656 hci_dev_unlock(hdev);
5657 return err;
5658}
5659
Johan Hedberg5a154e62014-12-19 22:26:02 +02005660static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5661{
5662 struct hci_conn *conn;
5663
5664 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5665 if (!conn)
5666 return false;
5667
5668 if (conn->dst_type != type)
5669 return false;
5670
5671 if (conn->state != BT_CONNECTED)
5672 return false;
5673
5674 return true;
5675}
5676
5677/* This function requires the caller holds hdev->lock */
5678static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5679 u8 addr_type, u8 auto_connect)
5680{
5681 struct hci_dev *hdev = req->hdev;
5682 struct hci_conn_params *params;
5683
5684 params = hci_conn_params_add(hdev, addr, addr_type);
5685 if (!params)
5686 return -EIO;
5687
5688 if (params->auto_connect == auto_connect)
5689 return 0;
5690
5691 list_del_init(&params->action);
5692
5693 switch (auto_connect) {
5694 case HCI_AUTO_CONN_DISABLED:
5695 case HCI_AUTO_CONN_LINK_LOSS:
5696 __hci_update_background_scan(req);
5697 break;
5698 case HCI_AUTO_CONN_REPORT:
5699 list_add(&params->action, &hdev->pend_le_reports);
5700 __hci_update_background_scan(req);
5701 break;
5702 case HCI_AUTO_CONN_DIRECT:
5703 case HCI_AUTO_CONN_ALWAYS:
5704 if (!is_connected(hdev, addr, addr_type)) {
5705 list_add(&params->action, &hdev->pend_le_conns);
5706 __hci_update_background_scan(req);
5707 }
5708 break;
5709 }
5710
5711 params->auto_connect = auto_connect;
5712
5713 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5714 auto_connect);
5715
5716 return 0;
5717}
5718
Marcel Holtmann8afef092014-06-29 22:28:34 +02005719static void device_added(struct sock *sk, struct hci_dev *hdev,
5720 bdaddr_t *bdaddr, u8 type, u8 action)
5721{
5722 struct mgmt_ev_device_added ev;
5723
5724 bacpy(&ev.addr.bdaddr, bdaddr);
5725 ev.addr.type = type;
5726 ev.action = action;
5727
5728 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5729}
5730
Marcel Holtmann1904a852015-01-11 13:50:44 -08005731static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005732{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005733 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005734
5735 BT_DBG("status 0x%02x", status);
5736
5737 hci_dev_lock(hdev);
5738
5739 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5740 if (!cmd)
5741 goto unlock;
5742
5743 cmd->cmd_complete(cmd, mgmt_status(status));
5744 mgmt_pending_remove(cmd);
5745
5746unlock:
5747 hci_dev_unlock(hdev);
5748}
5749
Marcel Holtmann2faade52014-06-29 19:44:03 +02005750static int add_device(struct sock *sk, struct hci_dev *hdev,
5751 void *data, u16 len)
5752{
5753 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005754 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005755 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005756 u8 auto_conn, addr_type;
5757 int err;
5758
5759 BT_DBG("%s", hdev->name);
5760
Johan Hedberg66593582014-07-09 12:59:14 +03005761 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005762 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005763 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5764 MGMT_STATUS_INVALID_PARAMS,
5765 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005766
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005767 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005768 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5769 MGMT_STATUS_INVALID_PARAMS,
5770 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005771
Johan Hedberg5a154e62014-12-19 22:26:02 +02005772 hci_req_init(&req, hdev);
5773
Marcel Holtmann2faade52014-06-29 19:44:03 +02005774 hci_dev_lock(hdev);
5775
Johan Hedberg5a154e62014-12-19 22:26:02 +02005776 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5777 if (!cmd) {
5778 err = -ENOMEM;
5779 goto unlock;
5780 }
5781
5782 cmd->cmd_complete = addr_cmd_complete;
5783
Johan Hedberg66593582014-07-09 12:59:14 +03005784 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005785 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005786 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005787 err = cmd->cmd_complete(cmd,
5788 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005789 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005790 goto unlock;
5791 }
5792
5793 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5794 cp->addr.type);
5795 if (err)
5796 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005797
Johan Hedberg5a154e62014-12-19 22:26:02 +02005798 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005799
Johan Hedberg66593582014-07-09 12:59:14 +03005800 goto added;
5801 }
5802
Marcel Holtmann2faade52014-06-29 19:44:03 +02005803 if (cp->addr.type == BDADDR_LE_PUBLIC)
5804 addr_type = ADDR_LE_DEV_PUBLIC;
5805 else
5806 addr_type = ADDR_LE_DEV_RANDOM;
5807
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005808 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005809 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005810 else if (cp->action == 0x01)
5811 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005812 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005813 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005814
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005815 /* If the connection parameters don't exist for this device,
5816 * they will be created and configured with defaults.
5817 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005818 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005819 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005820 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005821 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005822 goto unlock;
5823 }
5824
Johan Hedberg66593582014-07-09 12:59:14 +03005825added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005826 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5827
Johan Hedberg5a154e62014-12-19 22:26:02 +02005828 err = hci_req_run(&req, add_device_complete);
5829 if (err < 0) {
5830 /* ENODATA means no HCI commands were needed (e.g. if
5831 * the adapter is powered off).
5832 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005833 if (err == -ENODATA)
5834 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005835 mgmt_pending_remove(cmd);
5836 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005837
5838unlock:
5839 hci_dev_unlock(hdev);
5840 return err;
5841}
5842
Marcel Holtmann8afef092014-06-29 22:28:34 +02005843static void device_removed(struct sock *sk, struct hci_dev *hdev,
5844 bdaddr_t *bdaddr, u8 type)
5845{
5846 struct mgmt_ev_device_removed ev;
5847
5848 bacpy(&ev.addr.bdaddr, bdaddr);
5849 ev.addr.type = type;
5850
5851 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5852}
5853
Marcel Holtmann1904a852015-01-11 13:50:44 -08005854static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005855{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005856 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005857
5858 BT_DBG("status 0x%02x", status);
5859
5860 hci_dev_lock(hdev);
5861
5862 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5863 if (!cmd)
5864 goto unlock;
5865
5866 cmd->cmd_complete(cmd, mgmt_status(status));
5867 mgmt_pending_remove(cmd);
5868
5869unlock:
5870 hci_dev_unlock(hdev);
5871}
5872
Marcel Holtmann2faade52014-06-29 19:44:03 +02005873static int remove_device(struct sock *sk, struct hci_dev *hdev,
5874 void *data, u16 len)
5875{
5876 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005877 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005878 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005879 int err;
5880
5881 BT_DBG("%s", hdev->name);
5882
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005883 hci_req_init(&req, hdev);
5884
Marcel Holtmann2faade52014-06-29 19:44:03 +02005885 hci_dev_lock(hdev);
5886
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005887 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5888 if (!cmd) {
5889 err = -ENOMEM;
5890 goto unlock;
5891 }
5892
5893 cmd->cmd_complete = addr_cmd_complete;
5894
Marcel Holtmann2faade52014-06-29 19:44:03 +02005895 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005896 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005897 u8 addr_type;
5898
Johan Hedberg66593582014-07-09 12:59:14 +03005899 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005900 err = cmd->cmd_complete(cmd,
5901 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005902 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005903 goto unlock;
5904 }
5905
Johan Hedberg66593582014-07-09 12:59:14 +03005906 if (cp->addr.type == BDADDR_BREDR) {
5907 err = hci_bdaddr_list_del(&hdev->whitelist,
5908 &cp->addr.bdaddr,
5909 cp->addr.type);
5910 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005911 err = cmd->cmd_complete(cmd,
5912 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005913 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005914 goto unlock;
5915 }
5916
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005917 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005918
Johan Hedberg66593582014-07-09 12:59:14 +03005919 device_removed(sk, hdev, &cp->addr.bdaddr,
5920 cp->addr.type);
5921 goto complete;
5922 }
5923
Marcel Holtmann2faade52014-06-29 19:44:03 +02005924 if (cp->addr.type == BDADDR_LE_PUBLIC)
5925 addr_type = ADDR_LE_DEV_PUBLIC;
5926 else
5927 addr_type = ADDR_LE_DEV_RANDOM;
5928
Johan Hedbergc71593d2014-07-02 17:37:28 +03005929 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5930 addr_type);
5931 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005932 err = cmd->cmd_complete(cmd,
5933 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005934 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005935 goto unlock;
5936 }
5937
5938 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005939 err = cmd->cmd_complete(cmd,
5940 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005941 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005942 goto unlock;
5943 }
5944
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005945 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005946 list_del(&params->list);
5947 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005948 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005949
5950 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005951 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005952 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005953 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005954
Marcel Holtmann2faade52014-06-29 19:44:03 +02005955 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005956 err = cmd->cmd_complete(cmd,
5957 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005958 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005959 goto unlock;
5960 }
5961
Johan Hedberg66593582014-07-09 12:59:14 +03005962 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5963 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5964 list_del(&b->list);
5965 kfree(b);
5966 }
5967
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005968 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005969
Johan Hedberg19de0822014-07-06 13:06:51 +03005970 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5971 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5972 continue;
5973 device_removed(sk, hdev, &p->addr, p->addr_type);
5974 list_del(&p->action);
5975 list_del(&p->list);
5976 kfree(p);
5977 }
5978
5979 BT_DBG("All LE connection parameters were removed");
5980
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005981 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005982 }
5983
Johan Hedberg66593582014-07-09 12:59:14 +03005984complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005985 err = hci_req_run(&req, remove_device_complete);
5986 if (err < 0) {
5987 /* ENODATA means no HCI commands were needed (e.g. if
5988 * the adapter is powered off).
5989 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005990 if (err == -ENODATA)
5991 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005992 mgmt_pending_remove(cmd);
5993 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005994
5995unlock:
5996 hci_dev_unlock(hdev);
5997 return err;
5998}
5999
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006000static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6001 u16 len)
6002{
6003 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006004 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6005 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006006 u16 param_count, expected_len;
6007 int i;
6008
6009 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006010 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6011 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006012
6013 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006014 if (param_count > max_param_count) {
6015 BT_ERR("load_conn_param: too big param_count value %u",
6016 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006017 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6018 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006019 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006020
6021 expected_len = sizeof(*cp) + param_count *
6022 sizeof(struct mgmt_conn_param);
6023 if (expected_len != len) {
6024 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6025 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006026 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6027 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006028 }
6029
6030 BT_DBG("%s param_count %u", hdev->name, param_count);
6031
6032 hci_dev_lock(hdev);
6033
6034 hci_conn_params_clear_disabled(hdev);
6035
6036 for (i = 0; i < param_count; i++) {
6037 struct mgmt_conn_param *param = &cp->params[i];
6038 struct hci_conn_params *hci_param;
6039 u16 min, max, latency, timeout;
6040 u8 addr_type;
6041
6042 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6043 param->addr.type);
6044
6045 if (param->addr.type == BDADDR_LE_PUBLIC) {
6046 addr_type = ADDR_LE_DEV_PUBLIC;
6047 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6048 addr_type = ADDR_LE_DEV_RANDOM;
6049 } else {
6050 BT_ERR("Ignoring invalid connection parameters");
6051 continue;
6052 }
6053
6054 min = le16_to_cpu(param->min_interval);
6055 max = le16_to_cpu(param->max_interval);
6056 latency = le16_to_cpu(param->latency);
6057 timeout = le16_to_cpu(param->timeout);
6058
6059 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6060 min, max, latency, timeout);
6061
6062 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6063 BT_ERR("Ignoring invalid connection parameters");
6064 continue;
6065 }
6066
6067 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6068 addr_type);
6069 if (!hci_param) {
6070 BT_ERR("Failed to add connection parameters");
6071 continue;
6072 }
6073
6074 hci_param->conn_min_interval = min;
6075 hci_param->conn_max_interval = max;
6076 hci_param->conn_latency = latency;
6077 hci_param->supervision_timeout = timeout;
6078 }
6079
6080 hci_dev_unlock(hdev);
6081
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006082 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6083 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006084}
6085
Marcel Holtmanndbece372014-07-04 18:11:55 +02006086static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6087 void *data, u16 len)
6088{
6089 struct mgmt_cp_set_external_config *cp = data;
6090 bool changed;
6091 int err;
6092
6093 BT_DBG("%s", hdev->name);
6094
6095 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006096 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6097 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006098
6099 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006100 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6101 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006102
6103 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006104 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6105 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006106
6107 hci_dev_lock(hdev);
6108
6109 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006110 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006111 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006112 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006113
6114 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6115 if (err < 0)
6116 goto unlock;
6117
6118 if (!changed)
6119 goto unlock;
6120
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006121 err = new_options(hdev, sk);
6122
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006123 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006124 mgmt_index_removed(hdev);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006125
Marcel Holtmann516018a2015-03-13 02:11:04 -07006126 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006127 hci_dev_set_flag(hdev, HCI_CONFIG);
6128 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006129
6130 queue_work(hdev->req_workqueue, &hdev->power_on);
6131 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006132 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b762014-07-06 12:11:14 +02006133 mgmt_index_added(hdev);
6134 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006135 }
6136
6137unlock:
6138 hci_dev_unlock(hdev);
6139 return err;
6140}
6141
Marcel Holtmann9713c172014-07-06 12:11:15 +02006142static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6143 void *data, u16 len)
6144{
6145 struct mgmt_cp_set_public_address *cp = data;
6146 bool changed;
6147 int err;
6148
6149 BT_DBG("%s", hdev->name);
6150
6151 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006152 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6153 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006154
6155 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006156 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6157 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006158
6159 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006160 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6161 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006162
6163 hci_dev_lock(hdev);
6164
6165 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6166 bacpy(&hdev->public_addr, &cp->bdaddr);
6167
6168 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6169 if (err < 0)
6170 goto unlock;
6171
6172 if (!changed)
6173 goto unlock;
6174
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006175 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006176 err = new_options(hdev, sk);
6177
6178 if (is_configured(hdev)) {
6179 mgmt_index_removed(hdev);
6180
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006181 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006182
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006183 hci_dev_set_flag(hdev, HCI_CONFIG);
6184 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006185
6186 queue_work(hdev->req_workqueue, &hdev->power_on);
6187 }
6188
6189unlock:
6190 hci_dev_unlock(hdev);
6191 return err;
6192}
6193
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006194static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006195 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006196 { read_version, MGMT_READ_VERSION_SIZE,
6197 HCI_MGMT_NO_HDEV },
6198 { read_commands, MGMT_READ_COMMANDS_SIZE,
6199 HCI_MGMT_NO_HDEV },
6200 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6201 HCI_MGMT_NO_HDEV },
6202 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6203 { set_powered, MGMT_SETTING_SIZE, 0 },
6204 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6205 { set_connectable, MGMT_SETTING_SIZE, 0 },
6206 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6207 { set_bondable, MGMT_SETTING_SIZE, 0 },
6208 { set_link_security, MGMT_SETTING_SIZE, 0 },
6209 { set_ssp, MGMT_SETTING_SIZE, 0 },
6210 { set_hs, MGMT_SETTING_SIZE, 0 },
6211 { set_le, MGMT_SETTING_SIZE, 0 },
6212 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6213 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6214 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6215 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6216 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6217 HCI_MGMT_VAR_LEN },
6218 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6219 HCI_MGMT_VAR_LEN },
6220 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6221 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6222 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6223 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6224 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6225 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6226 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6227 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6228 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6229 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6230 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6231 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6232 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6233 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6234 HCI_MGMT_VAR_LEN },
6235 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6236 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6237 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6238 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6239 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6240 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6241 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6242 { set_advertising, MGMT_SETTING_SIZE, 0 },
6243 { set_bredr, MGMT_SETTING_SIZE, 0 },
6244 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6245 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6246 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6247 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6248 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6249 { load_irks, MGMT_LOAD_IRKS_SIZE,
6250 HCI_MGMT_VAR_LEN },
6251 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6252 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6253 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6254 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6255 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6256 HCI_MGMT_VAR_LEN },
6257 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6258 HCI_MGMT_NO_HDEV },
6259 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6260 HCI_MGMT_UNCONFIGURED },
6261 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6262 HCI_MGMT_UNCONFIGURED },
6263 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6264 HCI_MGMT_UNCONFIGURED },
6265 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6266 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006267};
6268
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006269int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6270 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006271{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006272 void *buf;
6273 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006274 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006275 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006276 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006277 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006278 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006279 int err;
6280
6281 BT_DBG("got %zu bytes", msglen);
6282
6283 if (msglen < sizeof(*hdr))
6284 return -EINVAL;
6285
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006286 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006287 if (!buf)
6288 return -ENOMEM;
6289
Al Viro6ce8e9c2014-04-06 21:25:44 -04006290 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006291 err = -EFAULT;
6292 goto done;
6293 }
6294
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006295 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006296 opcode = __le16_to_cpu(hdr->opcode);
6297 index = __le16_to_cpu(hdr->index);
6298 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006299
6300 if (len != msglen - sizeof(*hdr)) {
6301 err = -EINVAL;
6302 goto done;
6303 }
6304
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006305 if (opcode >= chan->handler_count ||
6306 chan->handlers[opcode].func == NULL) {
6307 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006308 err = mgmt_cmd_status(sk, index, opcode,
6309 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006310 goto done;
6311 }
6312
6313 handler = &chan->handlers[opcode];
6314
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006315 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006316 hdev = hci_dev_get(index);
6317 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006318 err = mgmt_cmd_status(sk, index, opcode,
6319 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006320 goto done;
6321 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006322
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006323 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6324 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6325 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006326 err = mgmt_cmd_status(sk, index, opcode,
6327 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006328 goto done;
6329 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006330
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006331 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006332 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006333 err = mgmt_cmd_status(sk, index, opcode,
6334 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006335 goto done;
6336 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006337 }
6338
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006339 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6340 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006341 err = mgmt_cmd_status(sk, index, opcode,
6342 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006343 goto done;
6344 }
6345
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006346 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6347 if ((var_len && len < handler->data_len) ||
6348 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006349 err = mgmt_cmd_status(sk, index, opcode,
6350 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006351 goto done;
6352 }
6353
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006354 if (hdev)
6355 mgmt_init_hdev(sk, hdev);
6356
6357 cp = buf + sizeof(*hdr);
6358
Johan Hedbergbe22b542012-03-01 22:24:41 +02006359 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006360 if (err < 0)
6361 goto done;
6362
Johan Hedberg03811012010-12-08 00:21:06 +02006363 err = msglen;
6364
6365done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006366 if (hdev)
6367 hci_dev_put(hdev);
6368
Johan Hedberg03811012010-12-08 00:21:06 +02006369 kfree(buf);
6370 return err;
6371}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006372
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006373void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006374{
Marcel Holtmannced85542015-03-14 19:27:56 -07006375 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006376
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006377 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6378 return;
6379
Marcel Holtmannf9207332015-03-14 19:27:55 -07006380 switch (hdev->dev_type) {
6381 case HCI_BREDR:
6382 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6383 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6384 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006385 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006386 } else {
6387 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6388 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006389 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006390 }
6391 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006392 case HCI_AMP:
6393 ev.type = 0x02;
6394 break;
6395 default:
6396 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006397 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006398
6399 ev.bus = hdev->bus;
6400
6401 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
6402 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006403}
6404
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006405void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006406{
Marcel Holtmannced85542015-03-14 19:27:56 -07006407 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02006408 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006409
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006410 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6411 return;
6412
Marcel Holtmannf9207332015-03-14 19:27:55 -07006413 switch (hdev->dev_type) {
6414 case HCI_BREDR:
6415 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006416
Marcel Holtmannf9207332015-03-14 19:27:55 -07006417 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6418 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
6419 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006420 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006421 } else {
6422 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
6423 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006424 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006425 }
6426 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006427 case HCI_AMP:
6428 ev.type = 0x02;
6429 break;
6430 default:
6431 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006432 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006433
6434 ev.bus = hdev->bus;
6435
6436 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
6437 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006438}
6439
Andre Guedes6046dc32014-02-26 20:21:51 -03006440/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006441static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006442{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006443 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006444 struct hci_conn_params *p;
6445
6446 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006447 /* Needed for AUTO_OFF case where might not "really"
6448 * have been powered off.
6449 */
6450 list_del_init(&p->action);
6451
6452 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006453 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006454 case HCI_AUTO_CONN_ALWAYS:
6455 list_add(&p->action, &hdev->pend_le_conns);
6456 break;
6457 case HCI_AUTO_CONN_REPORT:
6458 list_add(&p->action, &hdev->pend_le_reports);
6459 break;
6460 default:
6461 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006462 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006463 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006464
Johan Hedberg2cf22212014-12-19 22:26:00 +02006465 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006466}
6467
Marcel Holtmann1904a852015-01-11 13:50:44 -08006468static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006469{
6470 struct cmd_lookup match = { NULL, hdev };
6471
6472 BT_DBG("status 0x%02x", status);
6473
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006474 if (!status) {
6475 /* Register the available SMP channels (BR/EDR and LE) only
6476 * when successfully powering on the controller. This late
6477 * registration is required so that LE SMP can clearly
6478 * decide if the public address or static address is used.
6479 */
6480 smp_register(hdev);
6481 }
6482
Johan Hedberg229ab392013-03-15 17:06:53 -05006483 hci_dev_lock(hdev);
6484
6485 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6486
6487 new_settings(hdev, match.sk);
6488
6489 hci_dev_unlock(hdev);
6490
6491 if (match.sk)
6492 sock_put(match.sk);
6493}
6494
Johan Hedberg70da6242013-03-15 17:06:51 -05006495static int powered_update_hci(struct hci_dev *hdev)
6496{
Johan Hedberg890ea892013-03-15 17:06:52 -05006497 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006498 u8 link_sec;
6499
Johan Hedberg890ea892013-03-15 17:06:52 -05006500 hci_req_init(&req, hdev);
6501
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006502 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006503 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006504 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006505
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006506 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006507
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006508 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6509 u8 support = 0x01;
6510
6511 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6512 sizeof(support), &support);
6513 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006514 }
6515
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006516 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006517 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006518 struct hci_cp_write_le_host_supported cp;
6519
Marcel Holtmann32226e42014-07-24 20:04:16 +02006520 cp.le = 0x01;
6521 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006522
6523 /* Check first if we already have the right
6524 * host state (host features set)
6525 */
6526 if (cp.le != lmp_host_le_capable(hdev) ||
6527 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006528 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6529 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006530 }
6531
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006532 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006533 /* Make sure the controller has a good default for
6534 * advertising data. This also applies to the case
6535 * where BR/EDR was toggled during the AUTO_OFF phase.
6536 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006537 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006538 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006539 update_scan_rsp_data(&req);
6540 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006541
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006542 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006543 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006544
6545 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006546 }
6547
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006548 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006549 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006550 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6551 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006552
6553 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006554 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006555 write_fast_connectable(&req, true);
6556 else
6557 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006558 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006559 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006560 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006561 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006562 }
6563
Johan Hedberg229ab392013-03-15 17:06:53 -05006564 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006565}
6566
Johan Hedberg744cf192011-11-08 20:40:14 +02006567int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006568{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006569 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006570 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006571 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006572
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006573 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006574 return 0;
6575
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006576 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006577 if (powered_update_hci(hdev) == 0)
6578 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006579
Johan Hedberg229ab392013-03-15 17:06:53 -05006580 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6581 &match);
6582 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006583 }
6584
Johan Hedberg229ab392013-03-15 17:06:53 -05006585 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006586
6587 /* If the power off is because of hdev unregistration let
6588 * use the appropriate INVALID_INDEX status. Otherwise use
6589 * NOT_POWERED. We cover both scenarios here since later in
6590 * mgmt_index_removed() any hci_conn callbacks will have already
6591 * been triggered, potentially causing misleading DISCONNECTED
6592 * status responses.
6593 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006594 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006595 status = MGMT_STATUS_INVALID_INDEX;
6596 else
6597 status = MGMT_STATUS_NOT_POWERED;
6598
6599 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006600
6601 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6602 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6603 zero_cod, sizeof(zero_cod), NULL);
6604
6605new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006606 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006607
6608 if (match.sk)
6609 sock_put(match.sk);
6610
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006611 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006612}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006613
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006614void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006615{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006616 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006617 u8 status;
6618
6619 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6620 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006621 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006622
6623 if (err == -ERFKILL)
6624 status = MGMT_STATUS_RFKILLED;
6625 else
6626 status = MGMT_STATUS_FAILED;
6627
Johan Hedberga69e8372015-03-06 21:08:53 +02006628 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006629
6630 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006631}
6632
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006633void mgmt_discoverable_timeout(struct hci_dev *hdev)
6634{
6635 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006636
6637 hci_dev_lock(hdev);
6638
6639 /* When discoverable timeout triggers, then just make sure
6640 * the limited discoverable flag is cleared. Even in the case
6641 * of a timeout triggered from general discoverable, it is
6642 * safe to unconditionally clear the flag.
6643 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006644 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
6645 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006646
6647 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006648 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006649 u8 scan = SCAN_PAGE;
6650 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6651 sizeof(scan), &scan);
6652 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006653 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006654 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006655 hci_req_run(&req, NULL);
6656
6657 hdev->discov_timeout = 0;
6658
Johan Hedberg9a43e252013-10-20 19:00:07 +03006659 new_settings(hdev, NULL);
6660
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006661 hci_dev_unlock(hdev);
6662}
6663
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006664void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6665 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006666{
Johan Hedberg86742e12011-11-07 23:13:38 +02006667 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006668
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006669 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006670
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006671 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006672 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006673 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006674 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006675 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006676 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006677
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006678 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006679}
Johan Hedbergf7520542011-01-20 12:34:39 +02006680
Johan Hedbergd7b25452014-05-23 13:19:53 +03006681static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6682{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006683 switch (ltk->type) {
6684 case SMP_LTK:
6685 case SMP_LTK_SLAVE:
6686 if (ltk->authenticated)
6687 return MGMT_LTK_AUTHENTICATED;
6688 return MGMT_LTK_UNAUTHENTICATED;
6689 case SMP_LTK_P256:
6690 if (ltk->authenticated)
6691 return MGMT_LTK_P256_AUTH;
6692 return MGMT_LTK_P256_UNAUTH;
6693 case SMP_LTK_P256_DEBUG:
6694 return MGMT_LTK_P256_DEBUG;
6695 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006696
6697 return MGMT_LTK_UNAUTHENTICATED;
6698}
6699
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006700void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006701{
6702 struct mgmt_ev_new_long_term_key ev;
6703
6704 memset(&ev, 0, sizeof(ev));
6705
Marcel Holtmann5192d302014-02-19 17:11:58 -08006706 /* Devices using resolvable or non-resolvable random addresses
6707 * without providing an indentity resolving key don't require
6708 * to store long term keys. Their addresses will change the
6709 * next time around.
6710 *
6711 * Only when a remote device provides an identity address
6712 * make sure the long term key is stored. If the remote
6713 * identity is known, the long term keys are internally
6714 * mapped to the identity address. So allow static random
6715 * and public addresses here.
6716 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006717 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6718 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6719 ev.store_hint = 0x00;
6720 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006721 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006722
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006723 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006724 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006725 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006726 ev.key.enc_size = key->enc_size;
6727 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006728 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006729
Johan Hedberg2ceba532014-06-16 19:25:16 +03006730 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006731 ev.key.master = 1;
6732
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006733 memcpy(ev.key.val, key->val, sizeof(key->val));
6734
Marcel Holtmann083368f2013-10-15 14:26:29 -07006735 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006736}
6737
Johan Hedberg95fbac82014-02-19 15:18:31 +02006738void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6739{
6740 struct mgmt_ev_new_irk ev;
6741
6742 memset(&ev, 0, sizeof(ev));
6743
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006744 /* For identity resolving keys from devices that are already
6745 * using a public address or static random address, do not
6746 * ask for storing this key. The identity resolving key really
6747 * is only mandatory for devices using resovlable random
6748 * addresses.
6749 *
6750 * Storing all identity resolving keys has the downside that
6751 * they will be also loaded on next boot of they system. More
6752 * identity resolving keys, means more time during scanning is
6753 * needed to actually resolve these addresses.
6754 */
6755 if (bacmp(&irk->rpa, BDADDR_ANY))
6756 ev.store_hint = 0x01;
6757 else
6758 ev.store_hint = 0x00;
6759
Johan Hedberg95fbac82014-02-19 15:18:31 +02006760 bacpy(&ev.rpa, &irk->rpa);
6761 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6762 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6763 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6764
6765 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6766}
6767
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006768void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6769 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006770{
6771 struct mgmt_ev_new_csrk ev;
6772
6773 memset(&ev, 0, sizeof(ev));
6774
6775 /* Devices using resolvable or non-resolvable random addresses
6776 * without providing an indentity resolving key don't require
6777 * to store signature resolving keys. Their addresses will change
6778 * the next time around.
6779 *
6780 * Only when a remote device provides an identity address
6781 * make sure the signature resolving key is stored. So allow
6782 * static random and public addresses here.
6783 */
6784 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6785 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6786 ev.store_hint = 0x00;
6787 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006788 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006789
6790 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6791 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006792 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006793 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6794
6795 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6796}
6797
Andre Guedesffb5a8272014-07-01 18:10:11 -03006798void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006799 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6800 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006801{
6802 struct mgmt_ev_new_conn_param ev;
6803
Johan Hedbergc103aea2014-07-02 17:37:34 +03006804 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6805 return;
6806
Andre Guedesffb5a8272014-07-01 18:10:11 -03006807 memset(&ev, 0, sizeof(ev));
6808 bacpy(&ev.addr.bdaddr, bdaddr);
6809 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006810 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006811 ev.min_interval = cpu_to_le16(min_interval);
6812 ev.max_interval = cpu_to_le16(max_interval);
6813 ev.latency = cpu_to_le16(latency);
6814 ev.timeout = cpu_to_le16(timeout);
6815
6816 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6817}
6818
Marcel Holtmann94933992013-10-15 10:26:39 -07006819static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6820 u8 data_len)
6821{
6822 eir[eir_len++] = sizeof(type) + data_len;
6823 eir[eir_len++] = type;
6824 memcpy(&eir[eir_len], data, data_len);
6825 eir_len += data_len;
6826
6827 return eir_len;
6828}
6829
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006830void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6831 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006832{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006833 char buf[512];
6834 struct mgmt_ev_device_connected *ev = (void *) buf;
6835 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006836
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006837 bacpy(&ev->addr.bdaddr, &conn->dst);
6838 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006839
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006840 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006841
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006842 /* We must ensure that the EIR Data fields are ordered and
6843 * unique. Keep it simple for now and avoid the problem by not
6844 * adding any BR/EDR data to the LE adv.
6845 */
6846 if (conn->le_adv_data_len > 0) {
6847 memcpy(&ev->eir[eir_len],
6848 conn->le_adv_data, conn->le_adv_data_len);
6849 eir_len = conn->le_adv_data_len;
6850 } else {
6851 if (name_len > 0)
6852 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6853 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006854
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006855 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006856 eir_len = eir_append_data(ev->eir, eir_len,
6857 EIR_CLASS_OF_DEV,
6858 conn->dev_class, 3);
6859 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006860
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006861 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006862
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006863 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6864 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006865}
6866
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006867static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006868{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006869 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006870
Johan Hedbergf5818c22014-12-05 13:36:02 +02006871 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006872
6873 *sk = cmd->sk;
6874 sock_hold(*sk);
6875
Johan Hedberga664b5b2011-02-19 12:06:02 -03006876 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006877}
6878
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006879static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006880{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006881 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006882 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006883
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006884 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6885
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006886 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006887 mgmt_pending_remove(cmd);
6888}
6889
Johan Hedberg84c61d92014-08-01 11:13:30 +03006890bool mgmt_powering_down(struct hci_dev *hdev)
6891{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006892 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006893 struct mgmt_mode *cp;
6894
6895 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6896 if (!cmd)
6897 return false;
6898
6899 cp = cmd->param;
6900 if (!cp->val)
6901 return true;
6902
6903 return false;
6904}
6905
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006906void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006907 u8 link_type, u8 addr_type, u8 reason,
6908 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006909{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006910 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006911 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006912
Johan Hedberg84c61d92014-08-01 11:13:30 +03006913 /* The connection is still in hci_conn_hash so test for 1
6914 * instead of 0 to know if this is the last one.
6915 */
6916 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6917 cancel_delayed_work(&hdev->power_off);
6918 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006919 }
6920
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006921 if (!mgmt_connected)
6922 return;
6923
Andre Guedes57eb7762013-10-30 19:01:41 -03006924 if (link_type != ACL_LINK && link_type != LE_LINK)
6925 return;
6926
Johan Hedberg744cf192011-11-08 20:40:14 +02006927 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006928
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006929 bacpy(&ev.addr.bdaddr, bdaddr);
6930 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6931 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006932
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006933 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006934
6935 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006936 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006937
Johan Hedberg124f6e32012-02-09 13:50:12 +02006938 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006939 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006940}
6941
Marcel Holtmann78929242013-10-06 23:55:47 -07006942void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6943 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006944{
Andre Guedes3655bba2013-10-30 19:01:40 -03006945 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6946 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006947 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006948
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006949 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6950 hdev);
6951
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006952 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006953 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006954 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006955
Andre Guedes3655bba2013-10-30 19:01:40 -03006956 cp = cmd->param;
6957
6958 if (bacmp(bdaddr, &cp->addr.bdaddr))
6959 return;
6960
6961 if (cp->addr.type != bdaddr_type)
6962 return;
6963
Johan Hedbergf5818c22014-12-05 13:36:02 +02006964 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006965 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006966}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006967
Marcel Holtmann445608d2013-10-06 23:55:48 -07006968void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6969 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006970{
6971 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006972
Johan Hedberg84c61d92014-08-01 11:13:30 +03006973 /* The connection is still in hci_conn_hash so test for 1
6974 * instead of 0 to know if this is the last one.
6975 */
6976 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6977 cancel_delayed_work(&hdev->power_off);
6978 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006979 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006980
Johan Hedberg4c659c32011-11-07 23:13:39 +02006981 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006982 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006983 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006984
Marcel Holtmann445608d2013-10-06 23:55:48 -07006985 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006986}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006987
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006988void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006989{
6990 struct mgmt_ev_pin_code_request ev;
6991
Johan Hedbergd8457692012-02-17 14:24:57 +02006992 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006993 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006994 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006995
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006996 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006997}
6998
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006999void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7000 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007001{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007002 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007003
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007004 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007005 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007006 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007007
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007008 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007009 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007010}
7011
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007012void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7013 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007014{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007015 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007016
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007017 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007018 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007019 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007020
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007021 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007022 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007023}
Johan Hedberga5c29682011-02-19 12:05:57 -03007024
Johan Hedberg744cf192011-11-08 20:40:14 +02007025int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007026 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007027 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007028{
7029 struct mgmt_ev_user_confirm_request ev;
7030
Johan Hedberg744cf192011-11-08 20:40:14 +02007031 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007032
Johan Hedberg272d90d2012-02-09 15:26:12 +02007033 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007034 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007035 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007036 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007037
Johan Hedberg744cf192011-11-08 20:40:14 +02007038 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007039 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007040}
7041
Johan Hedberg272d90d2012-02-09 15:26:12 +02007042int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007043 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007044{
7045 struct mgmt_ev_user_passkey_request ev;
7046
7047 BT_DBG("%s", hdev->name);
7048
Johan Hedberg272d90d2012-02-09 15:26:12 +02007049 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007050 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007051
7052 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007053 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007054}
7055
Brian Gix0df4c182011-11-16 13:53:13 -08007056static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007057 u8 link_type, u8 addr_type, u8 status,
7058 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007059{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007060 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007061
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007062 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007063 if (!cmd)
7064 return -ENOENT;
7065
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007066 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007067 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007068
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007069 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007070}
7071
Johan Hedberg744cf192011-11-08 20:40:14 +02007072int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007073 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007074{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007075 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007076 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007077}
7078
Johan Hedberg272d90d2012-02-09 15:26:12 +02007079int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007080 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007081{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007082 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007083 status,
7084 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007085}
Johan Hedberg2a611692011-02-19 12:06:00 -03007086
Brian Gix604086b2011-11-23 08:28:33 -08007087int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007088 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007089{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007090 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007091 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007092}
7093
Johan Hedberg272d90d2012-02-09 15:26:12 +02007094int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007095 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007096{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007097 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007098 status,
7099 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007100}
7101
Johan Hedberg92a25252012-09-06 18:39:26 +03007102int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7103 u8 link_type, u8 addr_type, u32 passkey,
7104 u8 entered)
7105{
7106 struct mgmt_ev_passkey_notify ev;
7107
7108 BT_DBG("%s", hdev->name);
7109
7110 bacpy(&ev.addr.bdaddr, bdaddr);
7111 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7112 ev.passkey = __cpu_to_le32(passkey);
7113 ev.entered = entered;
7114
7115 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7116}
7117
Johan Hedberge1e930f2014-09-08 17:09:49 -07007118void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007119{
7120 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007121 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007122 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007123
Johan Hedberge1e930f2014-09-08 17:09:49 -07007124 bacpy(&ev.addr.bdaddr, &conn->dst);
7125 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7126 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007127
Johan Hedberge1e930f2014-09-08 17:09:49 -07007128 cmd = find_pairing(conn);
7129
7130 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7131 cmd ? cmd->sk : NULL);
7132
Johan Hedberga511b352014-12-11 21:45:45 +02007133 if (cmd) {
7134 cmd->cmd_complete(cmd, status);
7135 mgmt_pending_remove(cmd);
7136 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007137}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007138
Marcel Holtmann464996a2013-10-15 14:26:24 -07007139void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007140{
7141 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007142 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007143
7144 if (status) {
7145 u8 mgmt_err = mgmt_status(status);
7146 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007147 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007148 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007149 }
7150
Marcel Holtmann464996a2013-10-15 14:26:24 -07007151 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007152 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007153 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007154 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007155
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007156 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007157 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007158
Johan Hedberg47990ea2012-02-22 11:58:37 +02007159 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007160 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007161
7162 if (match.sk)
7163 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007164}
7165
Johan Hedberg890ea892013-03-15 17:06:52 -05007166static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007167{
Johan Hedberg890ea892013-03-15 17:06:52 -05007168 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007169 struct hci_cp_write_eir cp;
7170
Johan Hedberg976eb202012-10-24 21:12:01 +03007171 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007172 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007173
Johan Hedbergc80da272012-02-22 15:38:48 +02007174 memset(hdev->eir, 0, sizeof(hdev->eir));
7175
Johan Hedbergcacaf522012-02-21 00:52:42 +02007176 memset(&cp, 0, sizeof(cp));
7177
Johan Hedberg890ea892013-03-15 17:06:52 -05007178 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007179}
7180
Marcel Holtmann3e248562013-10-15 14:26:25 -07007181void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007182{
7183 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007184 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007185 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007186
7187 if (status) {
7188 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007189
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007190 if (enable && hci_dev_test_and_clear_flag(hdev,
7191 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007192 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007193 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007194 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007195
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007196 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7197 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007198 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007199 }
7200
7201 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007202 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007203 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007204 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007205 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007206 changed = hci_dev_test_and_clear_flag(hdev,
7207 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007208 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007209 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007210 }
7211
7212 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7213
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007214 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007215 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007216
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007217 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007218 sock_put(match.sk);
7219
Johan Hedberg890ea892013-03-15 17:06:52 -05007220 hci_req_init(&req, hdev);
7221
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007222 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7223 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007224 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7225 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007226 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007227 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007228 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007229 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007230
7231 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007232}
7233
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007234static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007235{
7236 struct cmd_lookup *match = data;
7237
Johan Hedberg90e70452012-02-23 23:09:40 +02007238 if (match->sk == NULL) {
7239 match->sk = cmd->sk;
7240 sock_hold(match->sk);
7241 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007242}
7243
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007244void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7245 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007246{
Johan Hedberg90e70452012-02-23 23:09:40 +02007247 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007248
Johan Hedberg92da6092013-03-15 17:06:55 -05007249 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7250 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7251 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007252
7253 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007254 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7255 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007256
7257 if (match.sk)
7258 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007259}
7260
Marcel Holtmann7667da32013-10-15 14:26:27 -07007261void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007262{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007263 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007264 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007265
Johan Hedberg13928972013-03-15 17:07:00 -05007266 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007267 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007268
7269 memset(&ev, 0, sizeof(ev));
7270 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007271 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007272
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007273 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007274 if (!cmd) {
7275 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007276
Johan Hedberg13928972013-03-15 17:07:00 -05007277 /* If this is a HCI command related to powering on the
7278 * HCI dev don't send any mgmt signals.
7279 */
7280 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007281 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007282 }
7283
Marcel Holtmann7667da32013-10-15 14:26:27 -07007284 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7285 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007286}
Szymon Jancc35938b2011-03-22 13:12:21 +01007287
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007288void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007289 u8 *rand192, u8 *hash256, u8 *rand256,
7290 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007291{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007292 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007293
Johan Hedberg744cf192011-11-08 20:40:14 +02007294 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007295
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007296 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007297 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007298 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007299
7300 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007301 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7302 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007303 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007304 struct mgmt_rp_read_local_oob_data rp;
7305 size_t rp_size = sizeof(rp);
7306
7307 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7308 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7309
Johan Hedberg710f11c2014-05-26 11:21:22 +03007310 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007311 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007312 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007313 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007314 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007315 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007316
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007317 mgmt_cmd_complete(cmd->sk, hdev->id,
7318 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7319 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007320 }
7321
7322 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007323}
Johan Hedberge17acd42011-03-30 23:57:16 +03007324
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007325static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7326{
7327 int i;
7328
7329 for (i = 0; i < uuid_count; i++) {
7330 if (!memcmp(uuid, uuids[i], 16))
7331 return true;
7332 }
7333
7334 return false;
7335}
7336
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007337static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7338{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007339 u16 parsed = 0;
7340
7341 while (parsed < eir_len) {
7342 u8 field_len = eir[0];
7343 u8 uuid[16];
7344 int i;
7345
7346 if (field_len == 0)
7347 break;
7348
7349 if (eir_len - parsed < field_len + 1)
7350 break;
7351
7352 switch (eir[1]) {
7353 case EIR_UUID16_ALL:
7354 case EIR_UUID16_SOME:
7355 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007356 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007357 uuid[13] = eir[i + 3];
7358 uuid[12] = eir[i + 2];
7359 if (has_uuid(uuid, uuid_count, uuids))
7360 return true;
7361 }
7362 break;
7363 case EIR_UUID32_ALL:
7364 case EIR_UUID32_SOME:
7365 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007366 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007367 uuid[15] = eir[i + 5];
7368 uuid[14] = eir[i + 4];
7369 uuid[13] = eir[i + 3];
7370 uuid[12] = eir[i + 2];
7371 if (has_uuid(uuid, uuid_count, uuids))
7372 return true;
7373 }
7374 break;
7375 case EIR_UUID128_ALL:
7376 case EIR_UUID128_SOME:
7377 for (i = 0; i + 17 <= field_len; i += 16) {
7378 memcpy(uuid, eir + i + 2, 16);
7379 if (has_uuid(uuid, uuid_count, uuids))
7380 return true;
7381 }
7382 break;
7383 }
7384
7385 parsed += field_len + 1;
7386 eir += field_len + 1;
7387 }
7388
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007389 return false;
7390}
7391
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007392static void restart_le_scan(struct hci_dev *hdev)
7393{
7394 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007395 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007396 return;
7397
7398 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7399 hdev->discovery.scan_start +
7400 hdev->discovery.scan_duration))
7401 return;
7402
7403 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7404 DISCOV_LE_RESTART_DELAY);
7405}
7406
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007407static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7408 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7409{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007410 /* If a RSSI threshold has been specified, and
7411 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7412 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7413 * is set, let it through for further processing, as we might need to
7414 * restart the scan.
7415 *
7416 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7417 * the results are also dropped.
7418 */
7419 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7420 (rssi == HCI_RSSI_INVALID ||
7421 (rssi < hdev->discovery.rssi &&
7422 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7423 return false;
7424
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007425 if (hdev->discovery.uuid_count != 0) {
7426 /* If a list of UUIDs is provided in filter, results with no
7427 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007428 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007429 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7430 hdev->discovery.uuids) &&
7431 !eir_has_uuids(scan_rsp, scan_rsp_len,
7432 hdev->discovery.uuid_count,
7433 hdev->discovery.uuids))
7434 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007435 }
7436
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007437 /* If duplicate filtering does not report RSSI changes, then restart
7438 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007439 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007440 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7441 restart_le_scan(hdev);
7442
7443 /* Validate RSSI value against the RSSI threshold once more. */
7444 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7445 rssi < hdev->discovery.rssi)
7446 return false;
7447 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007448
7449 return true;
7450}
7451
Marcel Holtmann901801b2013-10-06 23:55:51 -07007452void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007453 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7454 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007455{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007456 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007457 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007458 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007459
Johan Hedberg75ce2082014-07-02 22:42:01 +03007460 /* Don't send events for a non-kernel initiated discovery. With
7461 * LE one exception is if we have pend_le_reports > 0 in which
7462 * case we're doing passive scanning and want these events.
7463 */
7464 if (!hci_discovery_active(hdev)) {
7465 if (link_type == ACL_LINK)
7466 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007467 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007468 return;
7469 }
Andre Guedes12602d02013-04-30 15:29:40 -03007470
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007471 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007472 /* We are using service discovery */
7473 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7474 scan_rsp_len))
7475 return;
7476 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007477
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007478 /* Make sure that the buffer is big enough. The 5 extra bytes
7479 * are for the potential CoD field.
7480 */
7481 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007482 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007483
Johan Hedberg1dc06092012-01-15 21:01:23 +02007484 memset(buf, 0, sizeof(buf));
7485
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007486 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7487 * RSSI value was reported as 0 when not available. This behavior
7488 * is kept when using device discovery. This is required for full
7489 * backwards compatibility with the API.
7490 *
7491 * However when using service discovery, the value 127 will be
7492 * returned when the RSSI is not available.
7493 */
Szymon Janc91200e92015-01-22 16:57:05 +01007494 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7495 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007496 rssi = 0;
7497
Johan Hedberg841c5642014-07-07 12:45:54 +03007498 bacpy(&ev->addr.bdaddr, bdaddr);
7499 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007500 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007501 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007502
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007503 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007504 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007505 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007506
Johan Hedberg1dc06092012-01-15 21:01:23 +02007507 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7508 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007509 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007510
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007511 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007512 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007513 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007514
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007515 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7516 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007517
Marcel Holtmann901801b2013-10-06 23:55:51 -07007518 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007519}
Johan Hedberga88a9652011-03-30 13:18:12 +03007520
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007521void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7522 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007523{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007524 struct mgmt_ev_device_found *ev;
7525 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7526 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007527
Johan Hedbergb644ba32012-01-17 21:48:47 +02007528 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007529
Johan Hedbergb644ba32012-01-17 21:48:47 +02007530 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007531
Johan Hedbergb644ba32012-01-17 21:48:47 +02007532 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007533 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007534 ev->rssi = rssi;
7535
7536 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007537 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007538
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007539 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007540
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007541 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007542}
Johan Hedberg314b2382011-04-27 10:29:57 -04007543
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007544void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007545{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007546 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007547
Andre Guedes343fb142011-11-22 17:14:19 -03007548 BT_DBG("%s discovering %u", hdev->name, discovering);
7549
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007550 memset(&ev, 0, sizeof(ev));
7551 ev.type = hdev->discovery.type;
7552 ev.discovering = discovering;
7553
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007554 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007555}
Antti Julku5e762442011-08-25 16:48:02 +03007556
Marcel Holtmann1904a852015-01-11 13:50:44 -08007557static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007558{
7559 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007560}
7561
7562void mgmt_reenable_advertising(struct hci_dev *hdev)
7563{
7564 struct hci_request req;
7565
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007566 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007567 return;
7568
7569 hci_req_init(&req, hdev);
7570 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007571 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007572}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007573
7574static struct hci_mgmt_chan chan = {
7575 .channel = HCI_CHANNEL_CONTROL,
7576 .handler_count = ARRAY_SIZE(mgmt_handlers),
7577 .handlers = mgmt_handlers,
7578};
7579
7580int mgmt_init(void)
7581{
7582 return hci_mgmt_chan_register(&chan);
7583}
7584
7585void mgmt_exit(void)
7586{
7587 hci_mgmt_chan_unregister(&chan);
7588}