blob: 6b58c13b2b51ce2db392363ddd7cb3ddb4913b30 [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,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200131};
132
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800133#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200134
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200135#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
136 "\x00\x00\x00\x00\x00\x00\x00\x00"
137
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200138struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200139 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200140 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200141 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100142 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200143 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200144 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300145 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200146 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200147};
148
Johan Hedbergca69b792011-11-11 18:10:00 +0200149/* HCI to MGMT error code conversion table */
150static u8 mgmt_status_table[] = {
151 MGMT_STATUS_SUCCESS,
152 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
153 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
154 MGMT_STATUS_FAILED, /* Hardware Failure */
155 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
156 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200157 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200158 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
159 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
160 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
161 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
162 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
163 MGMT_STATUS_BUSY, /* Command Disallowed */
164 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
165 MGMT_STATUS_REJECTED, /* Rejected Security */
166 MGMT_STATUS_REJECTED, /* Rejected Personal */
167 MGMT_STATUS_TIMEOUT, /* Host Timeout */
168 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
169 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
170 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
171 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
172 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
173 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
174 MGMT_STATUS_BUSY, /* Repeated Attempts */
175 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
176 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
177 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
178 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
179 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
180 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
181 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
182 MGMT_STATUS_FAILED, /* Unspecified Error */
183 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
184 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
185 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
186 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
187 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
188 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
189 MGMT_STATUS_FAILED, /* Unit Link Key Used */
190 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
191 MGMT_STATUS_TIMEOUT, /* Instant Passed */
192 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
193 MGMT_STATUS_FAILED, /* Transaction Collision */
194 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
195 MGMT_STATUS_REJECTED, /* QoS Rejected */
196 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
197 MGMT_STATUS_REJECTED, /* Insufficient Security */
198 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
199 MGMT_STATUS_BUSY, /* Role Switch Pending */
200 MGMT_STATUS_FAILED, /* Slot Violation */
201 MGMT_STATUS_FAILED, /* Role Switch Failed */
202 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
203 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
204 MGMT_STATUS_BUSY, /* Host Busy Pairing */
205 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
206 MGMT_STATUS_BUSY, /* Controller Busy */
207 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
208 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
209 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
210 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
211 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
212};
213
214static u8 mgmt_status(u8 hci_status)
215{
216 if (hci_status < ARRAY_SIZE(mgmt_status_table))
217 return mgmt_status_table[hci_status];
218
219 return MGMT_STATUS_FAILED;
220}
221
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200222static int mgmt_send_event(u16 event, struct hci_dev *hdev,
223 unsigned short channel, void *data, u16 data_len,
224 struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200225{
226 struct sk_buff *skb;
227 struct mgmt_hdr *hdr;
228
229 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
230 if (!skb)
231 return -ENOMEM;
232
233 hdr = (void *) skb_put(skb, sizeof(*hdr));
234 hdr->opcode = cpu_to_le16(event);
235 if (hdev)
236 hdr->index = cpu_to_le16(hdev->id);
237 else
238 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
239 hdr->len = cpu_to_le16(data_len);
240
241 if (data)
242 memcpy(skb_put(skb, data_len), data, data_len);
243
244 /* Time stamp */
245 __net_timestamp(skb);
246
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200247 hci_send_to_channel(channel, skb, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200248 kfree_skb(skb);
249
250 return 0;
251}
252
Marcel Holtmannf9207332015-03-14 19:27:55 -0700253static int mgmt_index_event(u16 event, struct hci_dev *hdev,
254 void *data, u16 data_len, int flag)
255{
256 struct sk_buff *skb;
257 struct mgmt_hdr *hdr;
258
259 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
260 if (!skb)
261 return -ENOMEM;
262
263 hdr = (void *) skb_put(skb, sizeof(*hdr));
264 hdr->opcode = cpu_to_le16(event);
265 hdr->index = cpu_to_le16(hdev->id);
266 hdr->len = cpu_to_le16(data_len);
267
268 if (data)
269 memcpy(skb_put(skb, data_len), data, data_len);
270
271 /* Time stamp */
272 __net_timestamp(skb);
273
274 hci_send_to_flagged_channel(HCI_CHANNEL_CONTROL, skb, flag);
275 kfree_skb(skb);
276
277 return 0;
278}
279
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200280static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
281 struct sock *skip_sk)
282{
283 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
284 skip_sk);
285}
286
Johan Hedberga69e8372015-03-06 21:08:53 +0200287static int mgmt_cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200288{
289 struct sk_buff *skb;
290 struct mgmt_hdr *hdr;
291 struct mgmt_ev_cmd_status *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300292 int err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200293
Szymon Janc34eb5252011-02-28 14:10:08 +0100294 BT_DBG("sock %p, index %u, cmd %u, status %u", sk, index, cmd, status);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200295
Andre Guedes790eff42012-06-07 19:05:46 -0300296 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev), GFP_KERNEL);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200297 if (!skb)
298 return -ENOMEM;
299
300 hdr = (void *) skb_put(skb, sizeof(*hdr));
301
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700302 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100303 hdr->index = cpu_to_le16(index);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200304 hdr->len = cpu_to_le16(sizeof(*ev));
305
306 ev = (void *) skb_put(skb, sizeof(*ev));
307 ev->status = status;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200308 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200309
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300310 err = sock_queue_rcv_skb(sk, skb);
311 if (err < 0)
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200312 kfree_skb(skb);
313
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300314 return err;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200315}
316
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200317static int mgmt_cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status,
318 void *rp, size_t rp_len)
Johan Hedberg02d98122010-12-13 21:07:04 +0200319{
320 struct sk_buff *skb;
321 struct mgmt_hdr *hdr;
322 struct mgmt_ev_cmd_complete *ev;
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300323 int err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200324
325 BT_DBG("sock %p", sk);
326
Andre Guedes790eff42012-06-07 19:05:46 -0300327 skb = alloc_skb(sizeof(*hdr) + sizeof(*ev) + rp_len, GFP_KERNEL);
Johan Hedberg02d98122010-12-13 21:07:04 +0200328 if (!skb)
329 return -ENOMEM;
330
331 hdr = (void *) skb_put(skb, sizeof(*hdr));
Johan Hedberga38528f2011-01-22 06:46:43 +0200332
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700333 hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
Szymon Janc4e51eae2011-02-25 19:05:48 +0100334 hdr->index = cpu_to_le16(index);
Johan Hedberga38528f2011-01-22 06:46:43 +0200335 hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200336
Johan Hedberga38528f2011-01-22 06:46:43 +0200337 ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200338 ev->opcode = cpu_to_le16(cmd);
Johan Hedbergaee9b212012-02-18 15:07:59 +0200339 ev->status = status;
Szymon Janc8020c162011-02-28 14:09:50 +0100340
341 if (rp)
342 memcpy(ev->data, rp, rp_len);
Johan Hedberg02d98122010-12-13 21:07:04 +0200343
Gustavo F. Padovan56b7d132011-10-14 19:20:01 -0300344 err = sock_queue_rcv_skb(sk, skb);
345 if (err < 0)
Johan Hedberg02d98122010-12-13 21:07:04 +0200346 kfree_skb(skb);
347
Marcel Holtmanne5f0e152012-02-22 11:59:01 +0100348 return err;
Johan Hedberg02d98122010-12-13 21:07:04 +0200349}
350
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300351static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
352 u16 data_len)
Johan Hedberga38528f2011-01-22 06:46:43 +0200353{
354 struct mgmt_rp_read_version rp;
355
356 BT_DBG("sock %p", sk);
357
358 rp.version = MGMT_VERSION;
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700359 rp.revision = cpu_to_le16(MGMT_REVISION);
Johan Hedberga38528f2011-01-22 06:46:43 +0200360
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200361 return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
362 &rp, sizeof(rp));
Johan Hedberga38528f2011-01-22 06:46:43 +0200363}
364
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300365static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
366 u16 data_len)
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200367{
368 struct mgmt_rp_read_commands *rp;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +0200369 const u16 num_commands = ARRAY_SIZE(mgmt_commands);
370 const u16 num_events = ARRAY_SIZE(mgmt_events);
Andrei Emeltchenko2e3c35e2012-03-14 18:54:15 +0200371 __le16 *opcode;
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200372 size_t rp_size;
373 int i, err;
374
375 BT_DBG("sock %p", sk);
376
377 rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
378
379 rp = kmalloc(rp_size, GFP_KERNEL);
380 if (!rp)
381 return -ENOMEM;
382
Joe Perchesdcf4adb2014-03-12 10:52:35 -0700383 rp->num_commands = cpu_to_le16(num_commands);
384 rp->num_events = cpu_to_le16(num_events);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200385
386 for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++)
387 put_unaligned_le16(mgmt_commands[i], opcode);
388
389 for (i = 0; i < num_events; i++, opcode++)
390 put_unaligned_le16(mgmt_events[i], opcode);
391
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200392 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
393 rp, rp_size);
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200394 kfree(rp);
395
396 return err;
397}
398
Gustavo F. Padovan04124682012-03-08 01:25:00 -0300399static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
400 u16 data_len)
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200401{
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200402 struct mgmt_rp_read_index_list *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200403 struct hci_dev *d;
Johan Hedberga38528f2011-01-22 06:46:43 +0200404 size_t rp_len;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200405 u16 count;
Johan Hedberg476e44c2012-10-19 20:10:46 +0300406 int err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200407
408 BT_DBG("sock %p", sk);
409
410 read_lock(&hci_dev_list_lock);
411
412 count = 0;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +0300413 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200414 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700415 !hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann1514b892013-10-06 08:25:01 -0700416 count++;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200417 }
418
Johan Hedberga38528f2011-01-22 06:46:43 +0200419 rp_len = sizeof(*rp) + (2 * count);
420 rp = kmalloc(rp_len, GFP_ATOMIC);
421 if (!rp) {
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100422 read_unlock(&hci_dev_list_lock);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200423 return -ENOMEM;
Jesper Juhlb2c60d42011-01-14 00:18:49 +0100424 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200425
Johan Hedberg476e44c2012-10-19 20:10:46 +0300426 count = 0;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +0200427 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700428 if (hci_dev_test_flag(d, HCI_SETUP) ||
429 hci_dev_test_flag(d, HCI_CONFIG) ||
430 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200431 continue;
432
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200433 /* Devices marked as raw-only are neither configured
434 * nor unconfigured controllers.
435 */
436 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
Marcel Holtmann0736cfa2013-08-26 21:40:51 -0700437 continue;
438
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200439 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700440 !hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann1514b892013-10-06 08:25:01 -0700441 rp->index[count++] = cpu_to_le16(d->id);
442 BT_DBG("Added hci%u", d->id);
443 }
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200444 }
445
Johan Hedberg476e44c2012-10-19 20:10:46 +0300446 rp->num_controllers = cpu_to_le16(count);
447 rp_len = sizeof(*rp) + (2 * count);
448
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200449 read_unlock(&hci_dev_list_lock);
450
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200451 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
452 0, rp, rp_len);
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200453
Johan Hedberga38528f2011-01-22 06:46:43 +0200454 kfree(rp);
455
456 return err;
Johan Hedbergfaba42e2010-12-13 21:07:05 +0200457}
458
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200459static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
460 void *data, u16 data_len)
461{
462 struct mgmt_rp_read_unconf_index_list *rp;
463 struct hci_dev *d;
464 size_t rp_len;
465 u16 count;
466 int err;
467
468 BT_DBG("sock %p", sk);
469
470 read_lock(&hci_dev_list_lock);
471
472 count = 0;
473 list_for_each_entry(d, &hci_dev_list, list) {
474 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700475 hci_dev_test_flag(d, HCI_UNCONFIGURED))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200476 count++;
477 }
478
479 rp_len = sizeof(*rp) + (2 * count);
480 rp = kmalloc(rp_len, GFP_ATOMIC);
481 if (!rp) {
482 read_unlock(&hci_dev_list_lock);
483 return -ENOMEM;
484 }
485
486 count = 0;
487 list_for_each_entry(d, &hci_dev_list, list) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700488 if (hci_dev_test_flag(d, HCI_SETUP) ||
489 hci_dev_test_flag(d, HCI_CONFIG) ||
490 hci_dev_test_flag(d, HCI_USER_CHANNEL))
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200491 continue;
492
493 /* Devices marked as raw-only are neither configured
494 * nor unconfigured controllers.
495 */
496 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
497 continue;
498
499 if (d->dev_type == HCI_BREDR &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700500 hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200501 rp->index[count++] = cpu_to_le16(d->id);
502 BT_DBG("Added hci%u", d->id);
503 }
504 }
505
506 rp->num_controllers = cpu_to_le16(count);
507 rp_len = sizeof(*rp) + (2 * count);
508
509 read_unlock(&hci_dev_list_lock);
510
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200511 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
512 MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
Marcel Holtmann73d1df22014-07-02 22:10:52 +0200513
514 kfree(rp);
515
516 return err;
517}
518
Marcel Holtmanndbece372014-07-04 18:11:55 +0200519static bool is_configured(struct hci_dev *hdev)
520{
521 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700522 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200523 return false;
524
525 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
526 !bacmp(&hdev->public_addr, BDADDR_ANY))
527 return false;
528
529 return true;
530}
531
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200532static __le32 get_missing_options(struct hci_dev *hdev)
533{
534 u32 options = 0;
535
Marcel Holtmanndbece372014-07-04 18:11:55 +0200536 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700537 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200538 options |= MGMT_OPTION_EXTERNAL_CONFIG;
539
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200540 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
541 !bacmp(&hdev->public_addr, BDADDR_ANY))
542 options |= MGMT_OPTION_PUBLIC_ADDRESS;
543
544 return cpu_to_le32(options);
545}
546
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200547static int new_options(struct hci_dev *hdev, struct sock *skip)
548{
549 __le32 options = get_missing_options(hdev);
550
551 return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
552 sizeof(options), skip);
553}
554
Marcel Holtmanndbece372014-07-04 18:11:55 +0200555static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
556{
557 __le32 options = get_missing_options(hdev);
558
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200559 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
560 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200561}
562
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200563static int read_config_info(struct sock *sk, struct hci_dev *hdev,
564 void *data, u16 data_len)
565{
566 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200567 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200568
569 BT_DBG("sock %p %s", sk, hdev->name);
570
571 hci_dev_lock(hdev);
572
573 memset(&rp, 0, sizeof(rp));
574 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200575
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200576 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
577 options |= MGMT_OPTION_EXTERNAL_CONFIG;
578
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200579 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200580 options |= MGMT_OPTION_PUBLIC_ADDRESS;
581
582 rp.supported_options = cpu_to_le32(options);
583 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200584
585 hci_dev_unlock(hdev);
586
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200587 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
588 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200589}
590
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200591static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200592{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200593 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200594
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200595 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300596 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800597 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300598 settings |= MGMT_SETTING_CONNECTABLE;
599 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200600
Andre Guedesed3fa312012-07-24 15:03:46 -0300601 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500602 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
603 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200604 settings |= MGMT_SETTING_BREDR;
605 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700606
607 if (lmp_ssp_capable(hdev)) {
608 settings |= MGMT_SETTING_SSP;
609 settings |= MGMT_SETTING_HS;
610 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800611
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800612 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800613 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700614 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100615
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300616 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200617 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300618 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300619 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200620 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800621 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300622 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200623
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200624 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
625 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200626 settings |= MGMT_SETTING_CONFIGURATION;
627
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200628 return settings;
629}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200630
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200631static u32 get_current_settings(struct hci_dev *hdev)
632{
633 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200634
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200635 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100636 settings |= MGMT_SETTING_POWERED;
637
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700638 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200639 settings |= MGMT_SETTING_CONNECTABLE;
640
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700641 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500642 settings |= MGMT_SETTING_FAST_CONNECTABLE;
643
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700644 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200645 settings |= MGMT_SETTING_DISCOVERABLE;
646
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700647 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300648 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200649
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700650 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200651 settings |= MGMT_SETTING_BREDR;
652
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700653 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200654 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200655
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700656 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200657 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200658
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700659 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200660 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200661
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700662 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200663 settings |= MGMT_SETTING_HS;
664
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700665 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300666 settings |= MGMT_SETTING_ADVERTISING;
667
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700668 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800669 settings |= MGMT_SETTING_SECURE_CONN;
670
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700671 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800672 settings |= MGMT_SETTING_DEBUG_KEYS;
673
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700674 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200675 settings |= MGMT_SETTING_PRIVACY;
676
Marcel Holtmann93690c22015-03-06 10:11:21 -0800677 /* The current setting for static address has two purposes. The
678 * first is to indicate if the static address will be used and
679 * the second is to indicate if it is actually set.
680 *
681 * This means if the static address is not configured, this flag
682 * will never bet set. If the address is configured, then if the
683 * address is actually used decides if the flag is set or not.
684 *
685 * For single mode LE only controllers and dual-mode controllers
686 * with BR/EDR disabled, the existence of the static address will
687 * be evaluated.
688 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700689 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700690 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800691 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
692 if (bacmp(&hdev->static_addr, BDADDR_ANY))
693 settings |= MGMT_SETTING_STATIC_ADDRESS;
694 }
695
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200696 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200697}
698
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300699#define PNP_INFO_SVCLASS_ID 0x1200
700
Johan Hedberg213202e2013-01-27 00:31:33 +0200701static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
702{
703 u8 *ptr = data, *uuids_start = NULL;
704 struct bt_uuid *uuid;
705
706 if (len < 4)
707 return ptr;
708
709 list_for_each_entry(uuid, &hdev->uuids, list) {
710 u16 uuid16;
711
712 if (uuid->size != 16)
713 continue;
714
715 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
716 if (uuid16 < 0x1100)
717 continue;
718
719 if (uuid16 == PNP_INFO_SVCLASS_ID)
720 continue;
721
722 if (!uuids_start) {
723 uuids_start = ptr;
724 uuids_start[0] = 1;
725 uuids_start[1] = EIR_UUID16_ALL;
726 ptr += 2;
727 }
728
729 /* Stop if not enough space to put next UUID */
730 if ((ptr - data) + sizeof(u16) > len) {
731 uuids_start[1] = EIR_UUID16_SOME;
732 break;
733 }
734
735 *ptr++ = (uuid16 & 0x00ff);
736 *ptr++ = (uuid16 & 0xff00) >> 8;
737 uuids_start[0] += sizeof(uuid16);
738 }
739
740 return ptr;
741}
742
Johan Hedbergcdf19632013-01-27 00:31:34 +0200743static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
744{
745 u8 *ptr = data, *uuids_start = NULL;
746 struct bt_uuid *uuid;
747
748 if (len < 6)
749 return ptr;
750
751 list_for_each_entry(uuid, &hdev->uuids, list) {
752 if (uuid->size != 32)
753 continue;
754
755 if (!uuids_start) {
756 uuids_start = ptr;
757 uuids_start[0] = 1;
758 uuids_start[1] = EIR_UUID32_ALL;
759 ptr += 2;
760 }
761
762 /* Stop if not enough space to put next UUID */
763 if ((ptr - data) + sizeof(u32) > len) {
764 uuids_start[1] = EIR_UUID32_SOME;
765 break;
766 }
767
768 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
769 ptr += sizeof(u32);
770 uuids_start[0] += sizeof(u32);
771 }
772
773 return ptr;
774}
775
Johan Hedbergc00d5752013-01-27 00:31:35 +0200776static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
777{
778 u8 *ptr = data, *uuids_start = NULL;
779 struct bt_uuid *uuid;
780
781 if (len < 18)
782 return ptr;
783
784 list_for_each_entry(uuid, &hdev->uuids, list) {
785 if (uuid->size != 128)
786 continue;
787
788 if (!uuids_start) {
789 uuids_start = ptr;
790 uuids_start[0] = 1;
791 uuids_start[1] = EIR_UUID128_ALL;
792 ptr += 2;
793 }
794
795 /* Stop if not enough space to put next UUID */
796 if ((ptr - data) + 16 > len) {
797 uuids_start[1] = EIR_UUID128_SOME;
798 break;
799 }
800
801 memcpy(ptr, uuid->uuid, 16);
802 ptr += 16;
803 uuids_start[0] += 16;
804 }
805
806 return ptr;
807}
808
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200809static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
810 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300811{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200812 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300813
814 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
815 if (cmd->opcode == opcode)
816 return cmd;
817 }
818
819 return NULL;
820}
821
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200822static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
823 struct hci_dev *hdev,
824 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300825{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200826 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300827
828 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
829 if (cmd->user_data != data)
830 continue;
831 if (cmd->opcode == opcode)
832 return cmd;
833 }
834
835 return NULL;
836}
837
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700838static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
839{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700840 u8 ad_len = 0;
841 size_t name_len;
842
843 name_len = strlen(hdev->dev_name);
844 if (name_len > 0) {
845 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
846
847 if (name_len > max_len) {
848 name_len = max_len;
849 ptr[1] = EIR_NAME_SHORT;
850 } else
851 ptr[1] = EIR_NAME_COMPLETE;
852
853 ptr[0] = name_len + 1;
854
855 memcpy(ptr + 2, hdev->dev_name, name_len);
856
857 ad_len += (name_len + 2);
858 ptr += (name_len + 2);
859 }
860
861 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700862}
863
864static void update_scan_rsp_data(struct hci_request *req)
865{
866 struct hci_dev *hdev = req->hdev;
867 struct hci_cp_le_set_scan_rsp_data cp;
868 u8 len;
869
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700870 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700871 return;
872
873 memset(&cp, 0, sizeof(cp));
874
875 len = create_scan_rsp_data(hdev, cp.data);
876
Johan Hedbergeb438b52013-10-16 15:31:07 +0300877 if (hdev->scan_rsp_data_len == len &&
878 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700879 return;
880
Johan Hedbergeb438b52013-10-16 15:31:07 +0300881 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
882 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700883
884 cp.length = len;
885
886 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
887}
888
Johan Hedberg9a43e252013-10-20 19:00:07 +0300889static u8 get_adv_discov_flags(struct hci_dev *hdev)
890{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200891 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300892
893 /* If there's a pending mgmt command the flags will not yet have
894 * their final values, so check for this first.
895 */
896 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
897 if (cmd) {
898 struct mgmt_mode *cp = cmd->param;
899 if (cp->val == 0x01)
900 return LE_AD_GENERAL;
901 else if (cp->val == 0x02)
902 return LE_AD_LIMITED;
903 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700904 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300905 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700906 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300907 return LE_AD_GENERAL;
908 }
909
910 return 0;
911}
912
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700913static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700914{
915 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700916
Johan Hedberg9a43e252013-10-20 19:00:07 +0300917 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700918
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700919 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700920 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700921
922 if (flags) {
923 BT_DBG("adv flags 0x%02x", flags);
924
925 ptr[0] = 2;
926 ptr[1] = EIR_FLAGS;
927 ptr[2] = flags;
928
929 ad_len += 3;
930 ptr += 3;
931 }
932
933 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
934 ptr[0] = 2;
935 ptr[1] = EIR_TX_POWER;
936 ptr[2] = (u8) hdev->adv_tx_power;
937
938 ad_len += 3;
939 ptr += 3;
940 }
941
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700942 return ad_len;
943}
944
Marcel Holtmann5947f4b2013-10-16 00:16:50 -0700945static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700946{
947 struct hci_dev *hdev = req->hdev;
948 struct hci_cp_le_set_adv_data cp;
949 u8 len;
950
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700951 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700952 return;
953
954 memset(&cp, 0, sizeof(cp));
955
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700956 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700957
958 if (hdev->adv_data_len == len &&
959 memcmp(cp.data, hdev->adv_data, len) == 0)
960 return;
961
962 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
963 hdev->adv_data_len = len;
964
965 cp.length = len;
966
967 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
968}
969
Johan Hedbergbc6d2d02014-07-10 12:09:08 +0300970int mgmt_update_adv_data(struct hci_dev *hdev)
971{
972 struct hci_request req;
973
974 hci_req_init(&req, hdev);
975 update_adv_data(&req);
976
977 return hci_req_run(&req, NULL);
978}
979
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300980static void create_eir(struct hci_dev *hdev, u8 *data)
981{
982 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300983 size_t name_len;
984
985 name_len = strlen(hdev->dev_name);
986
987 if (name_len > 0) {
988 /* EIR Data type */
989 if (name_len > 48) {
990 name_len = 48;
991 ptr[1] = EIR_NAME_SHORT;
992 } else
993 ptr[1] = EIR_NAME_COMPLETE;
994
995 /* EIR Data length */
996 ptr[0] = name_len + 1;
997
998 memcpy(ptr + 2, hdev->dev_name, name_len);
999
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001000 ptr += (name_len + 2);
1001 }
1002
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001003 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001004 ptr[0] = 2;
1005 ptr[1] = EIR_TX_POWER;
1006 ptr[2] = (u8) hdev->inq_tx_power;
1007
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001008 ptr += 3;
1009 }
1010
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001011 if (hdev->devid_source > 0) {
1012 ptr[0] = 9;
1013 ptr[1] = EIR_DEVICE_ID;
1014
1015 put_unaligned_le16(hdev->devid_source, ptr + 2);
1016 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1017 put_unaligned_le16(hdev->devid_product, ptr + 6);
1018 put_unaligned_le16(hdev->devid_version, ptr + 8);
1019
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001020 ptr += 10;
1021 }
1022
Johan Hedberg213202e2013-01-27 00:31:33 +02001023 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001024 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001025 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001026}
1027
Johan Hedberg890ea892013-03-15 17:06:52 -05001028static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001029{
Johan Hedberg890ea892013-03-15 17:06:52 -05001030 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001031 struct hci_cp_write_eir cp;
1032
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001033 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001034 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001035
Johan Hedberg976eb202012-10-24 21:12:01 +03001036 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001037 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001038
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001039 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001040 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001041
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001042 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001043 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001044
1045 memset(&cp, 0, sizeof(cp));
1046
1047 create_eir(hdev, cp.data);
1048
1049 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001050 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001051
1052 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1053
Johan Hedberg890ea892013-03-15 17:06:52 -05001054 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001055}
1056
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001057static u8 get_service_classes(struct hci_dev *hdev)
1058{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001059 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001060 u8 val = 0;
1061
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001062 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001063 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001064
1065 return val;
1066}
1067
Johan Hedberg890ea892013-03-15 17:06:52 -05001068static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001069{
Johan Hedberg890ea892013-03-15 17:06:52 -05001070 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001071 u8 cod[3];
1072
1073 BT_DBG("%s", hdev->name);
1074
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001075 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001076 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001077
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001078 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001079 return;
1080
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001081 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001082 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001083
1084 cod[0] = hdev->minor_class;
1085 cod[1] = hdev->major_class;
1086 cod[2] = get_service_classes(hdev);
1087
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001088 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001089 cod[1] |= 0x20;
1090
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001091 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001092 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001093
Johan Hedberg890ea892013-03-15 17:06:52 -05001094 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001095}
1096
Johan Hedberga4858cb2014-02-25 19:56:31 +02001097static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001098{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001099 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001100
1101 /* If there's a pending mgmt command the flag will not yet have
1102 * it's final value, so check for this first.
1103 */
1104 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1105 if (cmd) {
1106 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001107 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001108 }
1109
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001110 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001111}
1112
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001113static void disable_advertising(struct hci_request *req)
1114{
1115 u8 enable = 0x00;
1116
1117 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1118}
1119
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001120static void enable_advertising(struct hci_request *req)
1121{
1122 struct hci_dev *hdev = req->hdev;
1123 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001124 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001125 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001126
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001127 if (hci_conn_num(hdev, LE_LINK) > 0)
1128 return;
1129
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001130 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001131 disable_advertising(req);
1132
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001133 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001134 * hci_update_random_address knows that it's safe to go ahead
1135 * and write a new random address. The flag will be set back on
1136 * as soon as the SET_ADV_ENABLE HCI command completes.
1137 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001138 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001139
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001140 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001141 connectable = true;
1142 else
1143 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001144
Johan Hedberga4858cb2014-02-25 19:56:31 +02001145 /* Set require_privacy to true only when non-connectable
1146 * advertising is used. In that case it is fine to use a
1147 * non-resolvable private address.
1148 */
1149 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001150 return;
1151
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001152 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001153 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1154 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001155 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001156 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001157 cp.channel_map = hdev->le_adv_channel_map;
1158
1159 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1160
1161 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1162}
1163
Johan Hedberg7d785252011-12-15 00:47:39 +02001164static void service_cache_off(struct work_struct *work)
1165{
1166 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001167 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001168 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001169
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001170 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001171 return;
1172
Johan Hedberg890ea892013-03-15 17:06:52 -05001173 hci_req_init(&req, hdev);
1174
Johan Hedberg7d785252011-12-15 00:47:39 +02001175 hci_dev_lock(hdev);
1176
Johan Hedberg890ea892013-03-15 17:06:52 -05001177 update_eir(&req);
1178 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001179
1180 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001181
1182 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001183}
1184
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001185static void rpa_expired(struct work_struct *work)
1186{
1187 struct hci_dev *hdev = container_of(work, struct hci_dev,
1188 rpa_expired.work);
1189 struct hci_request req;
1190
1191 BT_DBG("");
1192
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001193 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001194
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001195 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001196 return;
1197
1198 /* The generation of a new RPA and programming it into the
1199 * controller happens in the enable_advertising() function.
1200 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001201 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001202 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001203 hci_req_run(&req, NULL);
1204}
1205
Johan Hedberg6a919082012-02-28 06:17:26 +02001206static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001207{
Marcel Holtmann238be782015-03-13 02:11:06 -07001208 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001209 return;
1210
Johan Hedberg4f87da82012-03-02 19:55:56 +02001211 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001212 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001213
Johan Hedberg4f87da82012-03-02 19:55:56 +02001214 /* Non-mgmt controlled devices get this bit set
1215 * implicitly so that pairing works for them, however
1216 * for mgmt we require user-space to explicitly enable
1217 * it
1218 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001219 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001220}
1221
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001222static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001223 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001224{
1225 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001226
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001227 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001228
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001229 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001230
Johan Hedberg03811012010-12-08 00:21:06 +02001231 memset(&rp, 0, sizeof(rp));
1232
Johan Hedberg03811012010-12-08 00:21:06 +02001233 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001234
1235 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001236 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001237
1238 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1239 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1240
1241 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001242
1243 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001244 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001245
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001246 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001247
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001248 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1249 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001250}
1251
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001252static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001253{
1254 sock_put(cmd->sk);
1255 kfree(cmd->param);
1256 kfree(cmd);
1257}
1258
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001259static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1260 struct hci_dev *hdev,
1261 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001262{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001263 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001264
Johan Hedbergfca20012014-06-28 17:54:05 +03001265 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001266 if (!cmd)
1267 return NULL;
1268
1269 cmd->opcode = opcode;
1270 cmd->index = hdev->id;
1271
Johan Hedberg323b0b82014-12-05 13:36:01 +02001272 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001273 if (!cmd->param) {
1274 kfree(cmd);
1275 return NULL;
1276 }
1277
Johan Hedberg323b0b82014-12-05 13:36:01 +02001278 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001279
1280 cmd->sk = sk;
1281 sock_hold(sk);
1282
1283 list_add(&cmd->list, &hdev->mgmt_pending);
1284
1285 return cmd;
1286}
1287
1288static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001289 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001290 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001291 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001292{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001293 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001294
Andre Guedesa3d09352013-02-01 11:21:30 -03001295 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001296 if (opcode > 0 && cmd->opcode != opcode)
1297 continue;
1298
1299 cb(cmd, data);
1300 }
1301}
1302
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001303static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001304{
1305 list_del(&cmd->list);
1306 mgmt_pending_free(cmd);
1307}
1308
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001309static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001310{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001311 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001312
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001313 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1314 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001315}
1316
Marcel Holtmann1904a852015-01-11 13:50:44 -08001317static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001318{
1319 BT_DBG("%s status 0x%02x", hdev->name, status);
1320
Johan Hedberga3172b72014-02-28 09:33:44 +02001321 if (hci_conn_count(hdev) == 0) {
1322 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001323 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001324 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001325}
1326
Johan Hedberg23a48092014-07-08 16:05:06 +03001327static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001328{
1329 struct hci_dev *hdev = req->hdev;
1330 struct hci_cp_remote_name_req_cancel cp;
1331 struct inquiry_entry *e;
1332
1333 switch (hdev->discovery.state) {
1334 case DISCOVERY_FINDING:
1335 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1336 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1337 } else {
1338 cancel_delayed_work(&hdev->le_scan_disable);
1339 hci_req_add_le_scan_disable(req);
1340 }
1341
Johan Hedberg23a48092014-07-08 16:05:06 +03001342 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001343
1344 case DISCOVERY_RESOLVING:
1345 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1346 NAME_PENDING);
1347 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001348 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001349
1350 bacpy(&cp.bdaddr, &e->data.bdaddr);
1351 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1352 &cp);
1353
Johan Hedberg23a48092014-07-08 16:05:06 +03001354 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001355
1356 default:
1357 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001358 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001359 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001360 return true;
1361 }
1362
Johan Hedberg21a60d32014-06-10 14:05:58 +03001363 break;
1364 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001365
1366 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001367}
1368
Johan Hedberg8b064a32014-02-24 14:52:22 +02001369static int clean_up_hci_state(struct hci_dev *hdev)
1370{
1371 struct hci_request req;
1372 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001373 bool discov_stopped;
1374 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001375
1376 hci_req_init(&req, hdev);
1377
1378 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1379 test_bit(HCI_PSCAN, &hdev->flags)) {
1380 u8 scan = 0x00;
1381 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1382 }
1383
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001384 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001385 disable_advertising(&req);
1386
Johan Hedberg23a48092014-07-08 16:05:06 +03001387 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001388
1389 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1390 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001391 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001392
Johan Hedbergc9910d02014-02-27 14:35:12 +02001393 switch (conn->state) {
1394 case BT_CONNECTED:
1395 case BT_CONFIG:
1396 dc.handle = cpu_to_le16(conn->handle);
1397 dc.reason = 0x15; /* Terminated due to Power Off */
1398 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1399 break;
1400 case BT_CONNECT:
1401 if (conn->type == LE_LINK)
1402 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1403 0, NULL);
1404 else if (conn->type == ACL_LINK)
1405 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1406 6, &conn->dst);
1407 break;
1408 case BT_CONNECT2:
1409 bacpy(&rej.bdaddr, &conn->dst);
1410 rej.reason = 0x15; /* Terminated due to Power Off */
1411 if (conn->type == ACL_LINK)
1412 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1413 sizeof(rej), &rej);
1414 else if (conn->type == SCO_LINK)
1415 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1416 sizeof(rej), &rej);
1417 break;
1418 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001419 }
1420
Johan Hedberg23a48092014-07-08 16:05:06 +03001421 err = hci_req_run(&req, clean_up_hci_complete);
1422 if (!err && discov_stopped)
1423 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1424
1425 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001426}
1427
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001428static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001429 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001430{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001431 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001432 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001433 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001434
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001435 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001436
Johan Hedberga7e80f22013-01-09 16:05:19 +02001437 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001438 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1439 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001440
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001441 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001442
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001443 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001444 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1445 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001446 goto failed;
1447 }
1448
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001449 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001450 cancel_delayed_work(&hdev->power_off);
1451
1452 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001453 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1454 data, len);
1455 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001456 goto failed;
1457 }
1458 }
1459
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001460 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001461 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001462 goto failed;
1463 }
1464
Johan Hedberg03811012010-12-08 00:21:06 +02001465 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1466 if (!cmd) {
1467 err = -ENOMEM;
1468 goto failed;
1469 }
1470
Johan Hedberg8b064a32014-02-24 14:52:22 +02001471 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001472 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001473 err = 0;
1474 } else {
1475 /* Disconnect connections, stop scans, etc */
1476 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001477 if (!err)
1478 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1479 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001480
Johan Hedberg8b064a32014-02-24 14:52:22 +02001481 /* ENODATA means there were no HCI commands queued */
1482 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001483 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001484 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1485 err = 0;
1486 }
1487 }
Johan Hedberg03811012010-12-08 00:21:06 +02001488
1489failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001490 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001491 return err;
1492}
1493
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001494static int new_settings(struct hci_dev *hdev, struct sock *skip)
1495{
1496 __le32 ev;
1497
1498 ev = cpu_to_le32(get_current_settings(hdev));
1499
1500 return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip);
1501}
1502
Johan Hedberg91a668b2014-07-09 13:28:26 +03001503int mgmt_new_settings(struct hci_dev *hdev)
1504{
1505 return new_settings(hdev, NULL);
1506}
1507
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001508struct cmd_lookup {
1509 struct sock *sk;
1510 struct hci_dev *hdev;
1511 u8 mgmt_status;
1512};
1513
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001514static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001515{
1516 struct cmd_lookup *match = data;
1517
1518 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1519
1520 list_del(&cmd->list);
1521
1522 if (match->sk == NULL) {
1523 match->sk = cmd->sk;
1524 sock_hold(match->sk);
1525 }
1526
1527 mgmt_pending_free(cmd);
1528}
1529
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001530static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001531{
1532 u8 *status = data;
1533
Johan Hedberga69e8372015-03-06 21:08:53 +02001534 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001535 mgmt_pending_remove(cmd);
1536}
1537
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001538static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001539{
1540 if (cmd->cmd_complete) {
1541 u8 *status = data;
1542
1543 cmd->cmd_complete(cmd, *status);
1544 mgmt_pending_remove(cmd);
1545
1546 return;
1547 }
1548
1549 cmd_status_rsp(cmd, data);
1550}
1551
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001552static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001553{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001554 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1555 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001556}
1557
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001558static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001559{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001560 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1561 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001562}
1563
Johan Hedberge6fe7982013-10-02 15:45:22 +03001564static u8 mgmt_bredr_support(struct hci_dev *hdev)
1565{
1566 if (!lmp_bredr_capable(hdev))
1567 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001568 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001569 return MGMT_STATUS_REJECTED;
1570 else
1571 return MGMT_STATUS_SUCCESS;
1572}
1573
1574static u8 mgmt_le_support(struct hci_dev *hdev)
1575{
1576 if (!lmp_le_capable(hdev))
1577 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001578 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001579 return MGMT_STATUS_REJECTED;
1580 else
1581 return MGMT_STATUS_SUCCESS;
1582}
1583
Marcel Holtmann1904a852015-01-11 13:50:44 -08001584static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1585 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001586{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001587 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001588 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001589 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001590 bool changed;
1591
1592 BT_DBG("status 0x%02x", status);
1593
1594 hci_dev_lock(hdev);
1595
1596 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1597 if (!cmd)
1598 goto unlock;
1599
1600 if (status) {
1601 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001602 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001603 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001604 goto remove_cmd;
1605 }
1606
1607 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001608 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001609 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001610
1611 if (hdev->discov_timeout > 0) {
1612 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1613 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1614 to);
1615 }
1616 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001617 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001618 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001619
1620 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1621
1622 if (changed)
1623 new_settings(hdev, cmd->sk);
1624
Marcel Holtmann970ba522013-10-15 06:33:57 -07001625 /* When the discoverable mode gets changed, make sure
1626 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001627 * bit correctly set. Also update page scan based on whitelist
1628 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001629 */
1630 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001631 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001632 update_class(&req);
1633 hci_req_run(&req, NULL);
1634
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001635remove_cmd:
1636 mgmt_pending_remove(cmd);
1637
1638unlock:
1639 hci_dev_unlock(hdev);
1640}
1641
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001642static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001643 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001644{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001645 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001646 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001647 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001648 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001649 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001650 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001651
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001652 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001653
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001654 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1655 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001656 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1657 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001658
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001659 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001660 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1661 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001662
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001663 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001664
1665 /* Disabling discoverable requires that no timeout is set,
1666 * and enabling limited discoverable requires a timeout.
1667 */
1668 if ((cp->val == 0x00 && timeout > 0) ||
1669 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001670 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1671 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001673 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001674
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001675 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001676 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1677 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001678 goto failed;
1679 }
1680
1681 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001682 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001683 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1684 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001685 goto failed;
1686 }
1687
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001688 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001689 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1690 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001691 goto failed;
1692 }
1693
1694 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001695 bool changed = false;
1696
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001697 /* Setting limited discoverable when powered off is
1698 * not a valid operation since it requires a timeout
1699 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1700 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001701 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001702 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001703 changed = true;
1704 }
1705
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001706 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001707 if (err < 0)
1708 goto failed;
1709
1710 if (changed)
1711 err = new_settings(hdev, sk);
1712
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001713 goto failed;
1714 }
1715
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001716 /* If the current mode is the same, then just update the timeout
1717 * value with the new value. And if only the timeout gets updated,
1718 * then no need for any HCI transactions.
1719 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001720 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1721 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1722 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001723 cancel_delayed_work(&hdev->discov_off);
1724 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001725
Marcel Holtmann36261542013-10-15 08:28:51 -07001726 if (cp->val && hdev->discov_timeout > 0) {
1727 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001728 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001729 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001730 }
1731
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001732 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001733 goto failed;
1734 }
1735
1736 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1737 if (!cmd) {
1738 err = -ENOMEM;
1739 goto failed;
1740 }
1741
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001742 /* Cancel any potential discoverable timeout that might be
1743 * still active and store new timeout value. The arming of
1744 * the timeout happens in the complete handler.
1745 */
1746 cancel_delayed_work(&hdev->discov_off);
1747 hdev->discov_timeout = timeout;
1748
Johan Hedbergb456f872013-10-19 23:38:22 +03001749 /* Limited discoverable mode */
1750 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001751 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001752 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001753 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001754
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001755 hci_req_init(&req, hdev);
1756
Johan Hedberg9a43e252013-10-20 19:00:07 +03001757 /* The procedure for LE-only controllers is much simpler - just
1758 * update the advertising data.
1759 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001760 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001761 goto update_ad;
1762
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001763 scan = SCAN_PAGE;
1764
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001765 if (cp->val) {
1766 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001767
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001768 if (cp->val == 0x02) {
1769 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001770 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001771 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1772 hci_cp.iac_lap[1] = 0x8b;
1773 hci_cp.iac_lap[2] = 0x9e;
1774 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1775 hci_cp.iac_lap[4] = 0x8b;
1776 hci_cp.iac_lap[5] = 0x9e;
1777 } else {
1778 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001779 hci_cp.num_iac = 1;
1780 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1781 hci_cp.iac_lap[1] = 0x8b;
1782 hci_cp.iac_lap[2] = 0x9e;
1783 }
1784
1785 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1786 (hci_cp.num_iac * 3) + 1, &hci_cp);
1787
1788 scan |= SCAN_INQUIRY;
1789 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001790 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001791 }
1792
1793 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001794
Johan Hedberg9a43e252013-10-20 19:00:07 +03001795update_ad:
1796 update_adv_data(&req);
1797
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001798 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001799 if (err < 0)
1800 mgmt_pending_remove(cmd);
1801
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001802failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001803 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001804 return err;
1805}
1806
Johan Hedberg406d7802013-03-15 17:07:09 -05001807static void write_fast_connectable(struct hci_request *req, bool enable)
1808{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001809 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001810 struct hci_cp_write_page_scan_activity acp;
1811 u8 type;
1812
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001813 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001814 return;
1815
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001816 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1817 return;
1818
Johan Hedberg406d7802013-03-15 17:07:09 -05001819 if (enable) {
1820 type = PAGE_SCAN_TYPE_INTERLACED;
1821
1822 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001823 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001824 } else {
1825 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1826
1827 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001828 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001829 }
1830
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001831 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001832
Johan Hedbergbd98b992013-03-15 17:07:13 -05001833 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1834 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1835 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1836 sizeof(acp), &acp);
1837
1838 if (hdev->page_scan_type != type)
1839 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001840}
1841
Marcel Holtmann1904a852015-01-11 13:50:44 -08001842static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1843 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001844{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001845 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001846 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001847 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001848
1849 BT_DBG("status 0x%02x", status);
1850
1851 hci_dev_lock(hdev);
1852
1853 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1854 if (!cmd)
1855 goto unlock;
1856
Johan Hedberg37438c12013-10-14 16:20:05 +03001857 if (status) {
1858 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001859 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001860 goto remove_cmd;
1861 }
1862
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001863 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001864 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001865 conn_changed = !hci_dev_test_and_set_flag(hdev,
1866 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001867 discov_changed = false;
1868 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001869 conn_changed = hci_dev_test_and_clear_flag(hdev,
1870 HCI_CONNECTABLE);
1871 discov_changed = hci_dev_test_and_clear_flag(hdev,
1872 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001873 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001874
Johan Hedberg2b76f452013-03-15 17:07:04 -05001875 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1876
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001877 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001878 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001879 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001880 if (discov_changed)
1881 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001882 hci_update_background_scan(hdev);
1883 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001884
Johan Hedberg37438c12013-10-14 16:20:05 +03001885remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001886 mgmt_pending_remove(cmd);
1887
1888unlock:
1889 hci_dev_unlock(hdev);
1890}
1891
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001892static int set_connectable_update_settings(struct hci_dev *hdev,
1893 struct sock *sk, u8 val)
1894{
1895 bool changed = false;
1896 int err;
1897
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001898 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001899 changed = true;
1900
1901 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001902 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001903 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001904 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1905 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001906 }
1907
1908 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1909 if (err < 0)
1910 return err;
1911
Johan Hedberg562064e2014-07-08 16:35:34 +03001912 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001913 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001914 hci_update_background_scan(hdev);
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001915 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001916 }
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001917
1918 return 0;
1919}
1920
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001921static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001922 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001923{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001924 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001925 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001926 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03001927 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001928 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001929
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001930 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02001931
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001932 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1933 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001934 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1935 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001936
Johan Hedberga7e80f22013-01-09 16:05:19 +02001937 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001938 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1939 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001940
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001941 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001942
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001943 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a1f2013-10-19 23:38:18 +03001944 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001945 goto failed;
1946 }
1947
1948 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001949 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001950 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
1951 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001952 goto failed;
1953 }
1954
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02001955 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
1956 if (!cmd) {
1957 err = -ENOMEM;
1958 goto failed;
1959 }
1960
Johan Hedberg2b76f452013-03-15 17:07:04 -05001961 hci_req_init(&req, hdev);
1962
Johan Hedberg9a43e252013-10-20 19:00:07 +03001963 /* If BR/EDR is not enabled and we disable advertising as a
1964 * by-product of disabling connectable, we need to update the
1965 * advertising flags.
1966 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001967 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03001968 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001969 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
1970 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03001971 }
1972 update_adv_data(&req);
1973 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03001974 if (cp->val) {
1975 scan = SCAN_PAGE;
1976 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03001977 /* If we don't have any whitelist entries just
1978 * disable all scanning. If there are entries
1979 * and we had both page and inquiry scanning
1980 * enabled then fall back to only page scanning.
1981 * Otherwise no changes are needed.
1982 */
1983 if (list_empty(&hdev->whitelist))
1984 scan = SCAN_DISABLED;
1985 else if (test_bit(HCI_ISCAN, &hdev->flags))
1986 scan = SCAN_PAGE;
1987 else
1988 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03001989
1990 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07001991 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03001992 cancel_delayed_work(&hdev->discov_off);
1993 }
1994
1995 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1996 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05001997
Johan Hedberg3bd27242014-07-28 20:53:58 +03001998no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03001999 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002000 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002001 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002002
Johan Hedberg2b76f452013-03-15 17:07:04 -05002003 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002004 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002005 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002006 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002007 err = set_connectable_update_settings(hdev, sk,
2008 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002009 goto failed;
2010 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002011
2012failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002013 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002014 return err;
2015}
2016
Johan Hedbergb2939472014-07-30 09:22:23 +03002017static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002018 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002019{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002020 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002021 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002022 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002023
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002024 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002025
Johan Hedberga7e80f22013-01-09 16:05:19 +02002026 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002027 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2028 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002029
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002030 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002031
2032 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002033 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002034 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002035 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002036
Johan Hedbergb2939472014-07-30 09:22:23 +03002037 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002038 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002039 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002040
Marcel Holtmann55594352013-10-06 16:11:57 -07002041 if (changed)
2042 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002043
Marcel Holtmann55594352013-10-06 16:11:57 -07002044unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002045 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002046 return err;
2047}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002048
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002049static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2050 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002051{
2052 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002053 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002054 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002055 int err;
2056
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002057 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002058
Johan Hedberge6fe7982013-10-02 15:45:22 +03002059 status = mgmt_bredr_support(hdev);
2060 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002061 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2062 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002063
Johan Hedberga7e80f22013-01-09 16:05:19 +02002064 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002065 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2066 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002067
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002068 hci_dev_lock(hdev);
2069
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002070 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002071 bool changed = false;
2072
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002073 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002074 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002075 changed = true;
2076 }
2077
2078 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2079 if (err < 0)
2080 goto failed;
2081
2082 if (changed)
2083 err = new_settings(hdev, sk);
2084
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002085 goto failed;
2086 }
2087
2088 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002089 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2090 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002091 goto failed;
2092 }
2093
2094 val = !!cp->val;
2095
2096 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2097 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2098 goto failed;
2099 }
2100
2101 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2102 if (!cmd) {
2103 err = -ENOMEM;
2104 goto failed;
2105 }
2106
2107 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2108 if (err < 0) {
2109 mgmt_pending_remove(cmd);
2110 goto failed;
2111 }
2112
2113failed:
2114 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002115 return err;
2116}
2117
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002118static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002119{
2120 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002121 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002122 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002123 int err;
2124
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002125 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002126
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002127 status = mgmt_bredr_support(hdev);
2128 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002129 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002130
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002131 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002132 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2133 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002134
Johan Hedberga7e80f22013-01-09 16:05:19 +02002135 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002136 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2137 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002138
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002139 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002140
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002141 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002142 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002143
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002144 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002145 changed = !hci_dev_test_and_set_flag(hdev,
2146 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002147 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002148 changed = hci_dev_test_and_clear_flag(hdev,
2149 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002150 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002151 changed = hci_dev_test_and_clear_flag(hdev,
2152 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002153 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002154 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002155 }
2156
2157 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2158 if (err < 0)
2159 goto failed;
2160
2161 if (changed)
2162 err = new_settings(hdev, sk);
2163
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002164 goto failed;
2165 }
2166
Johan Hedberg94d52da2015-02-19 17:38:06 +02002167 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002168 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2169 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002170 goto failed;
2171 }
2172
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002173 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002174 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2175 goto failed;
2176 }
2177
2178 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2179 if (!cmd) {
2180 err = -ENOMEM;
2181 goto failed;
2182 }
2183
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002184 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002185 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2186 sizeof(cp->val), &cp->val);
2187
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002188 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002189 if (err < 0) {
2190 mgmt_pending_remove(cmd);
2191 goto failed;
2192 }
2193
2194failed:
2195 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002196 return err;
2197}
2198
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002199static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002200{
2201 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002202 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002203 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002204 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002205
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002206 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002207
Johan Hedberge6fe7982013-10-02 15:45:22 +03002208 status = mgmt_bredr_support(hdev);
2209 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002210 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002211
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002212 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002213 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2214 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002215
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002216 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002217 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2218 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002219
Johan Hedberga7e80f22013-01-09 16:05:19 +02002220 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002221 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2222 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002223
Marcel Holtmannee392692013-10-01 22:59:23 -07002224 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002225
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002226 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002227 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2228 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002229 goto unlock;
2230 }
2231
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002232 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002233 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002234 } else {
2235 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002236 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2237 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002238 goto unlock;
2239 }
2240
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002241 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002242 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002243
2244 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2245 if (err < 0)
2246 goto unlock;
2247
2248 if (changed)
2249 err = new_settings(hdev, sk);
2250
2251unlock:
2252 hci_dev_unlock(hdev);
2253 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002254}
2255
Marcel Holtmann1904a852015-01-11 13:50:44 -08002256static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002257{
2258 struct cmd_lookup match = { NULL, hdev };
2259
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302260 hci_dev_lock(hdev);
2261
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002262 if (status) {
2263 u8 mgmt_err = mgmt_status(status);
2264
2265 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2266 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302267 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002268 }
2269
2270 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2271
2272 new_settings(hdev, match.sk);
2273
2274 if (match.sk)
2275 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002276
2277 /* Make sure the controller has a good default for
2278 * advertising data. Restrict the update to when LE
2279 * has actually been enabled. During power on, the
2280 * update in powered_update_hci will take care of it.
2281 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002282 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002283 struct hci_request req;
2284
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002285 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002286 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002287 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002288 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002289 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002290 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302291
2292unlock:
2293 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002294}
2295
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002296static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002297{
2298 struct mgmt_mode *cp = data;
2299 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002300 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002301 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002302 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002303 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002304
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002305 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002306
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002307 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002308 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2309 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002310
Johan Hedberga7e80f22013-01-09 16:05:19 +02002311 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002312 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2313 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002314
Johan Hedbergc73eee92013-04-19 18:35:21 +03002315 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002316 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002317 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2318 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002319
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002320 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002321
2322 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002323 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002324
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002325 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002326 bool changed = false;
2327
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002328 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002329 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002330 changed = true;
2331 }
2332
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002333 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002334 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002335 changed = true;
2336 }
2337
Johan Hedberg06199cf2012-02-22 16:37:11 +02002338 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2339 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002340 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002341
2342 if (changed)
2343 err = new_settings(hdev, sk);
2344
Johan Hedberg1de028c2012-02-29 19:55:35 -08002345 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002346 }
2347
Johan Hedberg4375f102013-09-25 13:26:10 +03002348 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2349 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002350 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2351 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002352 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002353 }
2354
2355 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2356 if (!cmd) {
2357 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002358 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002359 }
2360
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002361 hci_req_init(&req, hdev);
2362
Johan Hedberg06199cf2012-02-22 16:37:11 +02002363 memset(&hci_cp, 0, sizeof(hci_cp));
2364
2365 if (val) {
2366 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002367 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002368 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002369 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002370 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002371 }
2372
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002373 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2374 &hci_cp);
2375
2376 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302377 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002378 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002379
Johan Hedberg1de028c2012-02-29 19:55:35 -08002380unlock:
2381 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002382 return err;
2383}
2384
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002385/* This is a helper function to test for pending mgmt commands that can
2386 * cause CoD or EIR HCI commands. We can only allow one such pending
2387 * mgmt command at a time since otherwise we cannot easily track what
2388 * the current values are, will be, and based on that calculate if a new
2389 * HCI command needs to be sent and if yes with what value.
2390 */
2391static bool pending_eir_or_class(struct hci_dev *hdev)
2392{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002393 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002394
2395 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2396 switch (cmd->opcode) {
2397 case MGMT_OP_ADD_UUID:
2398 case MGMT_OP_REMOVE_UUID:
2399 case MGMT_OP_SET_DEV_CLASS:
2400 case MGMT_OP_SET_POWERED:
2401 return true;
2402 }
2403 }
2404
2405 return false;
2406}
2407
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002408static const u8 bluetooth_base_uuid[] = {
2409 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2410 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2411};
2412
2413static u8 get_uuid_size(const u8 *uuid)
2414{
2415 u32 val;
2416
2417 if (memcmp(uuid, bluetooth_base_uuid, 12))
2418 return 128;
2419
2420 val = get_unaligned_le32(&uuid[12]);
2421 if (val > 0xffff)
2422 return 32;
2423
2424 return 16;
2425}
2426
Johan Hedberg92da6092013-03-15 17:06:55 -05002427static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2428{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002429 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002430
2431 hci_dev_lock(hdev);
2432
2433 cmd = mgmt_pending_find(mgmt_op, hdev);
2434 if (!cmd)
2435 goto unlock;
2436
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002437 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2438 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002439
2440 mgmt_pending_remove(cmd);
2441
2442unlock:
2443 hci_dev_unlock(hdev);
2444}
2445
Marcel Holtmann1904a852015-01-11 13:50:44 -08002446static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002447{
2448 BT_DBG("status 0x%02x", status);
2449
2450 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2451}
2452
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002453static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002454{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002455 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002456 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002457 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002458 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002459 int err;
2460
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002461 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002462
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002463 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002464
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002465 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002466 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2467 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002468 goto failed;
2469 }
2470
Andre Guedes92c4c202012-06-07 19:05:44 -03002471 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002472 if (!uuid) {
2473 err = -ENOMEM;
2474 goto failed;
2475 }
2476
2477 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002478 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002479 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002480
Johan Hedbergde66aa62013-01-27 00:31:27 +02002481 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002482
Johan Hedberg890ea892013-03-15 17:06:52 -05002483 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002484
Johan Hedberg890ea892013-03-15 17:06:52 -05002485 update_class(&req);
2486 update_eir(&req);
2487
Johan Hedberg92da6092013-03-15 17:06:55 -05002488 err = hci_req_run(&req, add_uuid_complete);
2489 if (err < 0) {
2490 if (err != -ENODATA)
2491 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002492
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002493 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2494 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002495 goto failed;
2496 }
2497
2498 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002499 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002500 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002501 goto failed;
2502 }
2503
2504 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002505
2506failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002507 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002508 return err;
2509}
2510
Johan Hedberg24b78d02012-02-23 23:24:30 +02002511static bool enable_service_cache(struct hci_dev *hdev)
2512{
2513 if (!hdev_is_powered(hdev))
2514 return false;
2515
Marcel Holtmann238be782015-03-13 02:11:06 -07002516 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002517 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2518 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002519 return true;
2520 }
2521
2522 return false;
2523}
2524
Marcel Holtmann1904a852015-01-11 13:50:44 -08002525static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002526{
2527 BT_DBG("status 0x%02x", status);
2528
2529 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2530}
2531
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002532static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002533 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002534{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002535 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002536 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002537 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002538 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 -05002539 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002540 int err, found;
2541
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002542 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002543
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002544 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002545
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002546 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002547 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2548 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002549 goto unlock;
2550 }
2551
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002552 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002553 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002554
Johan Hedberg24b78d02012-02-23 23:24:30 +02002555 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002556 err = mgmt_cmd_complete(sk, hdev->id,
2557 MGMT_OP_REMOVE_UUID,
2558 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002559 goto unlock;
2560 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002561
Johan Hedberg9246a862012-02-23 21:33:16 +02002562 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002563 }
2564
2565 found = 0;
2566
Johan Hedberg056341c2013-01-27 00:31:30 +02002567 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002568 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2569 continue;
2570
2571 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002572 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002573 found++;
2574 }
2575
2576 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002577 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2578 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002579 goto unlock;
2580 }
2581
Johan Hedberg9246a862012-02-23 21:33:16 +02002582update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002583 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002584
Johan Hedberg890ea892013-03-15 17:06:52 -05002585 update_class(&req);
2586 update_eir(&req);
2587
Johan Hedberg92da6092013-03-15 17:06:55 -05002588 err = hci_req_run(&req, remove_uuid_complete);
2589 if (err < 0) {
2590 if (err != -ENODATA)
2591 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002592
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002593 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2594 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002595 goto unlock;
2596 }
2597
2598 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002599 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002600 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002601 goto unlock;
2602 }
2603
2604 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002605
2606unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002607 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002608 return err;
2609}
2610
Marcel Holtmann1904a852015-01-11 13:50:44 -08002611static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002612{
2613 BT_DBG("status 0x%02x", status);
2614
2615 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2616}
2617
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002618static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002619 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002620{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002621 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002622 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002623 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002624 int err;
2625
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002626 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002627
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002628 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002629 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2630 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002631
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002632 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002633
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002634 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002635 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2636 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002637 goto unlock;
2638 }
2639
2640 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002641 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2642 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002643 goto unlock;
2644 }
2645
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002646 hdev->major_class = cp->major;
2647 hdev->minor_class = cp->minor;
2648
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002649 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002650 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2651 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002652 goto unlock;
2653 }
2654
Johan Hedberg890ea892013-03-15 17:06:52 -05002655 hci_req_init(&req, hdev);
2656
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002657 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002658 hci_dev_unlock(hdev);
2659 cancel_delayed_work_sync(&hdev->service_cache);
2660 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002661 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002662 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002663
Johan Hedberg890ea892013-03-15 17:06:52 -05002664 update_class(&req);
2665
Johan Hedberg92da6092013-03-15 17:06:55 -05002666 err = hci_req_run(&req, set_class_complete);
2667 if (err < 0) {
2668 if (err != -ENODATA)
2669 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002670
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002671 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2672 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002673 goto unlock;
2674 }
2675
2676 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002677 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002678 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002679 goto unlock;
2680 }
2681
2682 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002683
Johan Hedbergb5235a62012-02-21 14:32:24 +02002684unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002685 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002686 return err;
2687}
2688
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002689static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002690 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002691{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002692 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002693 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2694 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002695 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002696 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002697 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002698
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002699 BT_DBG("request for %s", hdev->name);
2700
2701 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002702 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2703 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002704
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002705 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002706 if (key_count > max_key_count) {
2707 BT_ERR("load_link_keys: too big key_count value %u",
2708 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002709 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2710 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002711 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002712
Johan Hedberg86742e12011-11-07 23:13:38 +02002713 expected_len = sizeof(*cp) + key_count *
2714 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002715 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002716 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002717 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002718 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2719 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002720 }
2721
Johan Hedberg4ae14302013-01-20 14:27:13 +02002722 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002723 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2724 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002725
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002726 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002727 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002728
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002729 for (i = 0; i < key_count; i++) {
2730 struct mgmt_link_key_info *key = &cp->keys[i];
2731
Marcel Holtmann8e991132014-01-10 02:07:25 -08002732 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002733 return mgmt_cmd_status(sk, hdev->id,
2734 MGMT_OP_LOAD_LINK_KEYS,
2735 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002736 }
2737
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002738 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002739
2740 hci_link_keys_clear(hdev);
2741
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002742 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002743 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002744 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002745 changed = hci_dev_test_and_clear_flag(hdev,
2746 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002747
2748 if (changed)
2749 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002750
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002751 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002752 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002753
Johan Hedberg58e92932014-06-24 14:00:26 +03002754 /* Always ignore debug keys and require a new pairing if
2755 * the user wants to use them.
2756 */
2757 if (key->type == HCI_LK_DEBUG_COMBINATION)
2758 continue;
2759
Johan Hedberg7652ff62014-06-24 13:15:49 +03002760 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2761 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002762 }
2763
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002764 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002765
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002766 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002767
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002768 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002769}
2770
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002771static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002772 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002773{
2774 struct mgmt_ev_device_unpaired ev;
2775
2776 bacpy(&ev.addr.bdaddr, bdaddr);
2777 ev.addr.type = addr_type;
2778
2779 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002780 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002781}
2782
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002783static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002784 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002785{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002786 struct mgmt_cp_unpair_device *cp = data;
2787 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002788 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002789 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002790 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002791 int err;
2792
Johan Hedberga8a1d192011-11-10 15:54:38 +02002793 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002794 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2795 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002796
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002797 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002798 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2799 MGMT_STATUS_INVALID_PARAMS,
2800 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002801
Johan Hedberg118da702013-01-20 14:27:20 +02002802 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002803 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2804 MGMT_STATUS_INVALID_PARAMS,
2805 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002806
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002807 hci_dev_lock(hdev);
2808
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002809 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002810 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2811 MGMT_STATUS_NOT_POWERED, &rp,
2812 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002813 goto unlock;
2814 }
2815
Johan Hedberge0b2b272014-02-18 17:14:31 +02002816 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002817 /* If disconnection is requested, then look up the
2818 * connection. If the remote device is connected, it
2819 * will be later used to terminate the link.
2820 *
2821 * Setting it to NULL explicitly will cause no
2822 * termination of the link.
2823 */
2824 if (cp->disconnect)
2825 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2826 &cp->addr.bdaddr);
2827 else
2828 conn = NULL;
2829
Johan Hedberg124f6e32012-02-09 13:50:12 +02002830 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002831 } else {
2832 u8 addr_type;
2833
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002834 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2835 &cp->addr.bdaddr);
2836 if (conn) {
2837 /* Defer clearing up the connection parameters
2838 * until closing to give a chance of keeping
2839 * them if a repairing happens.
2840 */
2841 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2842
2843 /* If disconnection is not requested, then
2844 * clear the connection variable so that the
2845 * link is not terminated.
2846 */
2847 if (!cp->disconnect)
2848 conn = NULL;
2849 }
2850
Johan Hedberge0b2b272014-02-18 17:14:31 +02002851 if (cp->addr.type == BDADDR_LE_PUBLIC)
2852 addr_type = ADDR_LE_DEV_PUBLIC;
2853 else
2854 addr_type = ADDR_LE_DEV_RANDOM;
2855
Johan Hedberga7ec7332014-02-18 17:14:35 +02002856 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2857
Johan Hedberge0b2b272014-02-18 17:14:31 +02002858 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2859 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002860
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002861 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002862 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2863 MGMT_STATUS_NOT_PAIRED, &rp,
2864 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002865 goto unlock;
2866 }
2867
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002868 /* If the connection variable is set, then termination of the
2869 * link is requested.
2870 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002871 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002872 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2873 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002874 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002875 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002876 }
2877
Johan Hedberg124f6e32012-02-09 13:50:12 +02002878 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002879 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002880 if (!cmd) {
2881 err = -ENOMEM;
2882 goto unlock;
2883 }
2884
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002885 cmd->cmd_complete = addr_cmd_complete;
2886
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002887 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002888 dc.reason = 0x13; /* Remote User Terminated Connection */
2889 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2890 if (err < 0)
2891 mgmt_pending_remove(cmd);
2892
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002893unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002894 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002895 return err;
2896}
2897
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002898static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002899 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002900{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002901 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002902 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002903 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002904 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002905 int err;
2906
2907 BT_DBG("");
2908
Johan Hedberg06a63b12013-01-20 14:27:21 +02002909 memset(&rp, 0, sizeof(rp));
2910 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2911 rp.addr.type = cp->addr.type;
2912
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002913 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002914 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2915 MGMT_STATUS_INVALID_PARAMS,
2916 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002917
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002918 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002919
2920 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002921 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2922 MGMT_STATUS_NOT_POWERED, &rp,
2923 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002924 goto failed;
2925 }
2926
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002927 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002928 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2929 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002930 goto failed;
2931 }
2932
Andre Guedes591f47f2012-04-24 21:02:49 -03002933 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03002934 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2935 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02002936 else
2937 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03002938
Vishal Agarwalf9607272012-06-13 05:32:43 +05302939 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002940 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2941 MGMT_STATUS_NOT_CONNECTED, &rp,
2942 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002943 goto failed;
2944 }
2945
Johan Hedberg2e58ef32011-11-08 20:40:15 +02002946 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03002947 if (!cmd) {
2948 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002949 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03002950 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02002951
Johan Hedbergf5818c22014-12-05 13:36:02 +02002952 cmd->cmd_complete = generic_cmd_complete;
2953
Johan Hedberge3f2f922014-08-18 20:33:33 +03002954 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002955 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03002956 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002957
2958failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002959 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002960 return err;
2961}
2962
Andre Guedes57c14772012-04-24 21:02:50 -03002963static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02002964{
2965 switch (link_type) {
2966 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02002967 switch (addr_type) {
2968 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03002969 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03002970
Johan Hedberg48264f02011-11-09 13:58:58 +02002971 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002972 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002973 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02002974 }
Andre Guedes0ed09142012-04-03 08:46:54 -03002975
Johan Hedberg4c659c32011-11-07 23:13:39 +02002976 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03002977 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03002978 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02002979 }
2980}
2981
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002982static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
2983 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02002984{
Johan Hedberg2784eb42011-01-21 13:56:35 +02002985 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02002986 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02002987 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02002988 int err;
2989 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02002990
2991 BT_DBG("");
2992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002993 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02002994
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002995 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002996 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
2997 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02002998 goto unlock;
2999 }
3000
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003001 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003002 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3003 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003004 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003005 }
3006
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003007 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003008 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003009 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003010 err = -ENOMEM;
3011 goto unlock;
3012 }
3013
Johan Hedberg2784eb42011-01-21 13:56:35 +02003014 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003015 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003016 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3017 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003018 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003019 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003020 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003021 continue;
3022 i++;
3023 }
3024
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003025 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003026
Johan Hedberg4c659c32011-11-07 23:13:39 +02003027 /* Recalculate length in case of filtered SCO connections, etc */
3028 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003029
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003030 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3031 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003032
Johan Hedberga38528f2011-01-22 06:46:43 +02003033 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003034
3035unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003036 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003037 return err;
3038}
3039
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003040static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003041 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003042{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003043 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003044 int err;
3045
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003046 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003047 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003048 if (!cmd)
3049 return -ENOMEM;
3050
Johan Hedbergd8457692012-02-17 14:24:57 +02003051 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003052 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003053 if (err < 0)
3054 mgmt_pending_remove(cmd);
3055
3056 return err;
3057}
3058
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003059static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003060 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003061{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003062 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003063 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003064 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003065 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003066 int err;
3067
3068 BT_DBG("");
3069
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003070 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003071
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003072 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003073 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3074 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003075 goto failed;
3076 }
3077
Johan Hedbergd8457692012-02-17 14:24:57 +02003078 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003079 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003080 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3081 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003082 goto failed;
3083 }
3084
3085 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003086 struct mgmt_cp_pin_code_neg_reply ncp;
3087
3088 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003089
3090 BT_ERR("PIN code is not 16 bytes long");
3091
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003092 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003093 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003094 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3095 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003096
3097 goto failed;
3098 }
3099
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003100 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003101 if (!cmd) {
3102 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003103 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003104 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003105
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003106 cmd->cmd_complete = addr_cmd_complete;
3107
Johan Hedbergd8457692012-02-17 14:24:57 +02003108 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003109 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003110 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003111
3112 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3113 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003114 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003115
3116failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003117 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003118 return err;
3119}
3120
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003121static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3122 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003123{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003124 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003125
3126 BT_DBG("");
3127
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003128 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003129 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3130 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003131
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003132 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003133
3134 hdev->io_capability = cp->io_capability;
3135
3136 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003137 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003138
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003139 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003140
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003141 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3142 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003143}
3144
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003145static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003146{
3147 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003148 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003149
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003150 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003151 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3152 continue;
3153
Johan Hedberge9a416b2011-02-19 12:05:56 -03003154 if (cmd->user_data != conn)
3155 continue;
3156
3157 return cmd;
3158 }
3159
3160 return NULL;
3161}
3162
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003163static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003164{
3165 struct mgmt_rp_pair_device rp;
3166 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003167 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003168
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003169 bacpy(&rp.addr.bdaddr, &conn->dst);
3170 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003171
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003172 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3173 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003174
3175 /* So we don't get further callbacks for this connection */
3176 conn->connect_cfm_cb = NULL;
3177 conn->security_cfm_cb = NULL;
3178 conn->disconn_cfm_cb = NULL;
3179
David Herrmann76a68ba2013-04-06 20:28:37 +02003180 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003181
3182 /* The device is paired so there is no need to remove
3183 * its connection parameters anymore.
3184 */
3185 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003186
3187 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003188
3189 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003190}
3191
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003192void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3193{
3194 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003195 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003196
3197 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003198 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003199 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003200 mgmt_pending_remove(cmd);
3201 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003202}
3203
Johan Hedberge9a416b2011-02-19 12:05:56 -03003204static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3205{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003206 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003207
3208 BT_DBG("status %u", status);
3209
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003210 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003211 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003212 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003213 return;
3214 }
3215
3216 cmd->cmd_complete(cmd, mgmt_status(status));
3217 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003218}
3219
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003220static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303221{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003222 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303223
3224 BT_DBG("status %u", status);
3225
3226 if (!status)
3227 return;
3228
3229 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003230 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303231 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003232 return;
3233 }
3234
3235 cmd->cmd_complete(cmd, mgmt_status(status));
3236 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303237}
3238
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003239static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003240 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003241{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003242 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003243 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003244 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003245 u8 sec_level, auth_type;
3246 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003247 int err;
3248
3249 BT_DBG("");
3250
Szymon Jancf950a30e2013-01-18 12:48:07 +01003251 memset(&rp, 0, sizeof(rp));
3252 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3253 rp.addr.type = cp->addr.type;
3254
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003255 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003256 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3257 MGMT_STATUS_INVALID_PARAMS,
3258 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003259
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003260 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003261 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3262 MGMT_STATUS_INVALID_PARAMS,
3263 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003264
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003265 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003266
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003267 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003268 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3269 MGMT_STATUS_NOT_POWERED, &rp,
3270 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003271 goto unlock;
3272 }
3273
Johan Hedberg55e76b32015-03-10 22:34:40 +02003274 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3275 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3276 MGMT_STATUS_ALREADY_PAIRED, &rp,
3277 sizeof(rp));
3278 goto unlock;
3279 }
3280
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003281 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003282 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003283
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003284 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003285 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3286 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003287 } else {
3288 u8 addr_type;
3289
3290 /* Convert from L2CAP channel address type to HCI address type
3291 */
3292 if (cp->addr.type == BDADDR_LE_PUBLIC)
3293 addr_type = ADDR_LE_DEV_PUBLIC;
3294 else
3295 addr_type = ADDR_LE_DEV_RANDOM;
3296
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003297 /* When pairing a new device, it is expected to remember
3298 * this device for future connections. Adding the connection
3299 * parameter information ahead of time allows tracking
3300 * of the slave preferred values and will speed up any
3301 * further connection establishment.
3302 *
3303 * If connection parameters already exist, then they
3304 * will be kept and this function does nothing.
3305 */
3306 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3307
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003308 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003309 sec_level, HCI_LE_CONN_TIMEOUT,
3310 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003311 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003312
Ville Tervo30e76272011-02-22 16:10:53 -03003313 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003314 int status;
3315
3316 if (PTR_ERR(conn) == -EBUSY)
3317 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003318 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3319 status = MGMT_STATUS_NOT_SUPPORTED;
3320 else if (PTR_ERR(conn) == -ECONNREFUSED)
3321 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003322 else
3323 status = MGMT_STATUS_CONNECT_FAILED;
3324
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003325 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3326 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003327 goto unlock;
3328 }
3329
3330 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003331 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003332 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3333 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003334 goto unlock;
3335 }
3336
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003337 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003338 if (!cmd) {
3339 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003340 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003341 goto unlock;
3342 }
3343
Johan Hedberg04ab2742014-12-05 13:36:04 +02003344 cmd->cmd_complete = pairing_complete;
3345
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003346 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003347 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003348 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003349 conn->security_cfm_cb = pairing_complete_cb;
3350 conn->disconn_cfm_cb = pairing_complete_cb;
3351 } else {
3352 conn->connect_cfm_cb = le_pairing_complete_cb;
3353 conn->security_cfm_cb = le_pairing_complete_cb;
3354 conn->disconn_cfm_cb = le_pairing_complete_cb;
3355 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003356
Johan Hedberge9a416b2011-02-19 12:05:56 -03003357 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003358 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003359
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003360 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003361 hci_conn_security(conn, sec_level, auth_type, true)) {
3362 cmd->cmd_complete(cmd, 0);
3363 mgmt_pending_remove(cmd);
3364 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003365
3366 err = 0;
3367
3368unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003369 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003370 return err;
3371}
3372
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003373static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3374 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003375{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003376 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003377 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003378 struct hci_conn *conn;
3379 int err;
3380
3381 BT_DBG("");
3382
Johan Hedberg28424702012-02-02 04:02:29 +02003383 hci_dev_lock(hdev);
3384
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003385 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003386 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3387 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003388 goto unlock;
3389 }
3390
Johan Hedberg28424702012-02-02 04:02:29 +02003391 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3392 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003393 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3394 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003395 goto unlock;
3396 }
3397
3398 conn = cmd->user_data;
3399
3400 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003401 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3402 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003403 goto unlock;
3404 }
3405
Johan Hedberga511b352014-12-11 21:45:45 +02003406 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3407 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003408
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003409 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3410 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003411unlock:
3412 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003413 return err;
3414}
3415
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003416static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003417 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003418 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003419{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003420 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003421 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003422 int err;
3423
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003424 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003425
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003426 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003427 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3428 MGMT_STATUS_NOT_POWERED, addr,
3429 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003430 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003431 }
3432
Johan Hedberg1707c602013-03-15 17:07:15 -05003433 if (addr->type == BDADDR_BREDR)
3434 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003435 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003436 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003437
Johan Hedberg272d90d2012-02-09 15:26:12 +02003438 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003439 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3440 MGMT_STATUS_NOT_CONNECTED, addr,
3441 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003442 goto done;
3443 }
3444
Johan Hedberg1707c602013-03-15 17:07:15 -05003445 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003446 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003447 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003448 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3449 MGMT_STATUS_SUCCESS, addr,
3450 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003451 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003452 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3453 MGMT_STATUS_FAILED, addr,
3454 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003455
Brian Gix47c15e22011-11-16 13:53:14 -08003456 goto done;
3457 }
3458
Johan Hedberg1707c602013-03-15 17:07:15 -05003459 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003460 if (!cmd) {
3461 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003462 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003463 }
3464
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003465 cmd->cmd_complete = addr_cmd_complete;
3466
Brian Gix0df4c182011-11-16 13:53:13 -08003467 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003468 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3469 struct hci_cp_user_passkey_reply cp;
3470
Johan Hedberg1707c602013-03-15 17:07:15 -05003471 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003472 cp.passkey = passkey;
3473 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3474 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003475 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3476 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003477
Johan Hedberga664b5b2011-02-19 12:06:02 -03003478 if (err < 0)
3479 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003480
Brian Gix0df4c182011-11-16 13:53:13 -08003481done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003482 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003483 return err;
3484}
3485
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303486static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3487 void *data, u16 len)
3488{
3489 struct mgmt_cp_pin_code_neg_reply *cp = data;
3490
3491 BT_DBG("");
3492
Johan Hedberg1707c602013-03-15 17:07:15 -05003493 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303494 MGMT_OP_PIN_CODE_NEG_REPLY,
3495 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3496}
3497
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003498static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3499 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003500{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003501 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003502
3503 BT_DBG("");
3504
3505 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003506 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3507 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003508
Johan Hedberg1707c602013-03-15 17:07:15 -05003509 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003510 MGMT_OP_USER_CONFIRM_REPLY,
3511 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003512}
3513
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003514static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003515 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003516{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003517 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003518
3519 BT_DBG("");
3520
Johan Hedberg1707c602013-03-15 17:07:15 -05003521 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003522 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3523 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003524}
3525
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003526static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3527 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003528{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003529 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003530
3531 BT_DBG("");
3532
Johan Hedberg1707c602013-03-15 17:07:15 -05003533 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003534 MGMT_OP_USER_PASSKEY_REPLY,
3535 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003536}
3537
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003538static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003539 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003540{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003541 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003542
3543 BT_DBG("");
3544
Johan Hedberg1707c602013-03-15 17:07:15 -05003545 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003546 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3547 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003548}
3549
Johan Hedberg13928972013-03-15 17:07:00 -05003550static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003551{
Johan Hedberg13928972013-03-15 17:07:00 -05003552 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003553 struct hci_cp_write_local_name cp;
3554
Johan Hedberg13928972013-03-15 17:07:00 -05003555 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003556
Johan Hedberg890ea892013-03-15 17:06:52 -05003557 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003558}
3559
Marcel Holtmann1904a852015-01-11 13:50:44 -08003560static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003561{
3562 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003563 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003564
3565 BT_DBG("status 0x%02x", status);
3566
3567 hci_dev_lock(hdev);
3568
3569 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3570 if (!cmd)
3571 goto unlock;
3572
3573 cp = cmd->param;
3574
3575 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003576 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3577 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003578 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003579 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3580 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003581
3582 mgmt_pending_remove(cmd);
3583
3584unlock:
3585 hci_dev_unlock(hdev);
3586}
3587
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003588static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003589 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003590{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003591 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003592 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003593 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003594 int err;
3595
3596 BT_DBG("");
3597
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003598 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003599
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003600 /* If the old values are the same as the new ones just return a
3601 * direct command complete event.
3602 */
3603 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3604 !memcmp(hdev->short_name, cp->short_name,
3605 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003606 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3607 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003608 goto failed;
3609 }
3610
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003611 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003612
Johan Hedbergb5235a62012-02-21 14:32:24 +02003613 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003614 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003615
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003616 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3617 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003618 if (err < 0)
3619 goto failed;
3620
3621 err = mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data, len,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003622 sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003623
Johan Hedbergb5235a62012-02-21 14:32:24 +02003624 goto failed;
3625 }
3626
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003627 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003628 if (!cmd) {
3629 err = -ENOMEM;
3630 goto failed;
3631 }
3632
Johan Hedberg13928972013-03-15 17:07:00 -05003633 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3634
Johan Hedberg890ea892013-03-15 17:06:52 -05003635 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003636
3637 if (lmp_bredr_capable(hdev)) {
3638 update_name(&req);
3639 update_eir(&req);
3640 }
3641
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003642 /* The name is stored in the scan response data and so
3643 * no need to udpate the advertising data here.
3644 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003645 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003646 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003647
Johan Hedberg13928972013-03-15 17:07:00 -05003648 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003649 if (err < 0)
3650 mgmt_pending_remove(cmd);
3651
3652failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003653 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003654 return err;
3655}
3656
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003657static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003658 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003659{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003660 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003661 int err;
3662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003663 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003664
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003665 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003666
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003667 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003668 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3669 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003670 goto unlock;
3671 }
3672
Andre Guedes9a1a1992012-07-24 15:03:48 -03003673 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003674 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3675 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003676 goto unlock;
3677 }
3678
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003679 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003680 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3681 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003682 goto unlock;
3683 }
3684
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003685 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003686 if (!cmd) {
3687 err = -ENOMEM;
3688 goto unlock;
3689 }
3690
Johan Hedberg710f11c2014-05-26 11:21:22 +03003691 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003692 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3693 0, NULL);
3694 else
3695 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3696
Szymon Jancc35938b2011-03-22 13:12:21 +01003697 if (err < 0)
3698 mgmt_pending_remove(cmd);
3699
3700unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003701 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003702 return err;
3703}
3704
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003705static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003706 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003707{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003708 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003709 int err;
3710
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003711 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003712
Johan Hedberg5d57e792015-01-23 10:10:38 +02003713 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003714 return mgmt_cmd_complete(sk, hdev->id,
3715 MGMT_OP_ADD_REMOTE_OOB_DATA,
3716 MGMT_STATUS_INVALID_PARAMS,
3717 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003718
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003719 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003720
Marcel Holtmannec109112014-01-10 02:07:30 -08003721 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3722 struct mgmt_cp_add_remote_oob_data *cp = data;
3723 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003724
Johan Hedbergc19a4952014-11-17 20:52:19 +02003725 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003726 err = mgmt_cmd_complete(sk, hdev->id,
3727 MGMT_OP_ADD_REMOTE_OOB_DATA,
3728 MGMT_STATUS_INVALID_PARAMS,
3729 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003730 goto unlock;
3731 }
3732
Marcel Holtmannec109112014-01-10 02:07:30 -08003733 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003734 cp->addr.type, cp->hash,
3735 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003736 if (err < 0)
3737 status = MGMT_STATUS_FAILED;
3738 else
3739 status = MGMT_STATUS_SUCCESS;
3740
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003741 err = mgmt_cmd_complete(sk, hdev->id,
3742 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3743 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003744 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3745 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003746 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003747 u8 status;
3748
Johan Hedberg86df9202014-10-26 20:52:27 +01003749 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003750 /* Enforce zero-valued 192-bit parameters as
3751 * long as legacy SMP OOB isn't implemented.
3752 */
3753 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3754 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003755 err = mgmt_cmd_complete(sk, hdev->id,
3756 MGMT_OP_ADD_REMOTE_OOB_DATA,
3757 MGMT_STATUS_INVALID_PARAMS,
3758 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003759 goto unlock;
3760 }
3761
Johan Hedberg86df9202014-10-26 20:52:27 +01003762 rand192 = NULL;
3763 hash192 = NULL;
3764 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003765 /* In case one of the P-192 values is set to zero,
3766 * then just disable OOB data for P-192.
3767 */
3768 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3769 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3770 rand192 = NULL;
3771 hash192 = NULL;
3772 } else {
3773 rand192 = cp->rand192;
3774 hash192 = cp->hash192;
3775 }
3776 }
3777
3778 /* In case one of the P-256 values is set to zero, then just
3779 * disable OOB data for P-256.
3780 */
3781 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3782 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3783 rand256 = NULL;
3784 hash256 = NULL;
3785 } else {
3786 rand256 = cp->rand256;
3787 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003788 }
3789
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003790 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003791 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003792 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003793 if (err < 0)
3794 status = MGMT_STATUS_FAILED;
3795 else
3796 status = MGMT_STATUS_SUCCESS;
3797
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003798 err = mgmt_cmd_complete(sk, hdev->id,
3799 MGMT_OP_ADD_REMOTE_OOB_DATA,
3800 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003801 } else {
3802 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003803 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3804 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003805 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003806
Johan Hedbergc19a4952014-11-17 20:52:19 +02003807unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003808 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003809 return err;
3810}
3811
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003812static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003813 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003814{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003815 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003816 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003817 int err;
3818
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003819 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003820
Johan Hedbergc19a4952014-11-17 20:52:19 +02003821 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003822 return mgmt_cmd_complete(sk, hdev->id,
3823 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3824 MGMT_STATUS_INVALID_PARAMS,
3825 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003826
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003827 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003828
Johan Hedbergeedbd582014-11-15 09:34:23 +02003829 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3830 hci_remote_oob_data_clear(hdev);
3831 status = MGMT_STATUS_SUCCESS;
3832 goto done;
3833 }
3834
Johan Hedberg6928a922014-10-26 20:46:09 +01003835 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003836 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003837 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003838 else
Szymon Janca6785be2012-12-13 15:11:21 +01003839 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003840
Johan Hedbergeedbd582014-11-15 09:34:23 +02003841done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003842 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3843 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003844
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003845 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003846 return err;
3847}
3848
Marcel Holtmann80190442014-12-04 11:36:36 +01003849static bool trigger_discovery(struct hci_request *req, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003850{
Marcel Holtmann80190442014-12-04 11:36:36 +01003851 struct hci_dev *hdev = req->hdev;
3852 struct hci_cp_le_set_scan_param param_cp;
3853 struct hci_cp_le_set_scan_enable enable_cp;
3854 struct hci_cp_inquiry inq_cp;
3855 /* General inquiry access code (GIAC) */
3856 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3857 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003858 int err;
3859
Marcel Holtmann80190442014-12-04 11:36:36 +01003860 switch (hdev->discovery.type) {
3861 case DISCOV_TYPE_BREDR:
3862 *status = mgmt_bredr_support(hdev);
3863 if (*status)
3864 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003865
Marcel Holtmann80190442014-12-04 11:36:36 +01003866 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
3867 *status = MGMT_STATUS_BUSY;
3868 return false;
3869 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003870
Marcel Holtmann80190442014-12-04 11:36:36 +01003871 hci_inquiry_cache_flush(hdev);
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003872
Marcel Holtmann80190442014-12-04 11:36:36 +01003873 memset(&inq_cp, 0, sizeof(inq_cp));
3874 memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
3875 inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
3876 hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
3877 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003878
Marcel Holtmann80190442014-12-04 11:36:36 +01003879 case DISCOV_TYPE_LE:
3880 case DISCOV_TYPE_INTERLEAVED:
3881 *status = mgmt_le_support(hdev);
3882 if (*status)
3883 return false;
3884
3885 if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003886 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003887 *status = MGMT_STATUS_NOT_SUPPORTED;
3888 return false;
3889 }
3890
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003891 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01003892 /* Don't let discovery abort an outgoing
3893 * connection attempt that's using directed
3894 * advertising.
3895 */
3896 if (hci_conn_hash_lookup_state(hdev, LE_LINK,
3897 BT_CONNECT)) {
3898 *status = MGMT_STATUS_REJECTED;
3899 return false;
3900 }
3901
3902 disable_advertising(req);
3903 }
3904
3905 /* If controller is scanning, it means the background scanning
3906 * is running. Thus, we should temporarily stop it in order to
3907 * set the discovery scanning parameters.
3908 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07003909 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
Marcel Holtmann80190442014-12-04 11:36:36 +01003910 hci_req_add_le_scan_disable(req);
3911
3912 memset(&param_cp, 0, sizeof(param_cp));
3913
3914 /* All active scans will be done with either a resolvable
3915 * private address (when privacy feature has been enabled)
Marcel Holtmann9437d2e2014-12-07 20:13:17 +01003916 * or non-resolvable private address.
Marcel Holtmann80190442014-12-04 11:36:36 +01003917 */
3918 err = hci_update_random_address(req, true, &own_addr_type);
3919 if (err < 0) {
3920 *status = MGMT_STATUS_FAILED;
3921 return false;
3922 }
3923
3924 param_cp.type = LE_SCAN_ACTIVE;
3925 param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
3926 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3927 param_cp.own_address_type = own_addr_type;
3928 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3929 &param_cp);
3930
3931 memset(&enable_cp, 0, sizeof(enable_cp));
3932 enable_cp.enable = LE_SCAN_ENABLE;
3933 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
3934 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
3935 &enable_cp);
3936 break;
3937
3938 default:
3939 *status = MGMT_STATUS_INVALID_PARAMS;
3940 return false;
3941 }
3942
3943 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003944}
3945
Marcel Holtmann1904a852015-01-11 13:50:44 -08003946static void start_discovery_complete(struct hci_dev *hdev, u8 status,
3947 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03003948{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003949 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003950 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003951
Andre Guedes7c307722013-04-30 15:29:28 -03003952 BT_DBG("status %d", status);
3953
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003954 hci_dev_lock(hdev);
3955
3956 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01003957 if (!cmd)
3958 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
3959
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003960 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02003961 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003962 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03003963 }
3964
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003965 if (status) {
3966 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
3967 goto unlock;
3968 }
3969
Andre Guedes7c307722013-04-30 15:29:28 -03003970 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03003971
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003972 /* If the scan involves LE scan, pick proper timeout to schedule
3973 * hdev->le_scan_disable that will stop it.
3974 */
Andre Guedes7c307722013-04-30 15:29:28 -03003975 switch (hdev->discovery.type) {
3976 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01003977 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03003978 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003979 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01003980 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03003981 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003982 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003983 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03003984 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003985 default:
3986 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01003987 timeout = 0;
3988 break;
Andre Guedes7c307722013-04-30 15:29:28 -03003989 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01003990
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08003991 if (timeout) {
3992 /* When service discovery is used and the controller has
3993 * a strict duplicate filter, it is important to remember
3994 * the start and duration of the scan. This is required
3995 * for restarting scanning during the discovery phase.
3996 */
3997 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
3998 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08003999 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004000 hdev->discovery.scan_start = jiffies;
4001 hdev->discovery.scan_duration = timeout;
4002 }
4003
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004004 queue_delayed_work(hdev->workqueue,
4005 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004006 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004007
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004008unlock:
4009 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004010}
4011
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004012static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004013 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004014{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004015 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004016 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004017 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004018 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004019 int err;
4020
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004021 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004022
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004023 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004024
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004025 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004026 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4027 MGMT_STATUS_NOT_POWERED,
4028 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004029 goto failed;
4030 }
4031
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004032 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004033 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004034 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4035 MGMT_STATUS_BUSY, &cp->type,
4036 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004037 goto failed;
4038 }
4039
Johan Hedberg2922a942014-12-05 13:36:06 +02004040 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004041 if (!cmd) {
4042 err = -ENOMEM;
4043 goto failed;
4044 }
4045
Johan Hedberg2922a942014-12-05 13:36:06 +02004046 cmd->cmd_complete = generic_cmd_complete;
4047
Marcel Holtmann22078802014-12-05 11:45:22 +01004048 /* Clear the discovery filter first to free any previously
4049 * allocated memory for the UUID list.
4050 */
4051 hci_discovery_filter_clear(hdev);
4052
Andre Guedes4aab14e2012-02-17 20:39:36 -03004053 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004054 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004055
Andre Guedes7c307722013-04-30 15:29:28 -03004056 hci_req_init(&req, hdev);
4057
Marcel Holtmann80190442014-12-04 11:36:36 +01004058 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004059 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4060 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004061 mgmt_pending_remove(cmd);
4062 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004063 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004064
Andre Guedes7c307722013-04-30 15:29:28 -03004065 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004066 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004067 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004068 goto failed;
4069 }
4070
4071 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004072
4073failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004074 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004075 return err;
4076}
4077
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004078static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4079 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004080{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004081 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4082 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004083}
4084
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004085static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4086 void *data, u16 len)
4087{
4088 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004089 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004090 struct hci_request req;
4091 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4092 u16 uuid_count, expected_len;
4093 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004094 int err;
4095
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004096 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004097
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004098 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004099
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004100 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004101 err = mgmt_cmd_complete(sk, hdev->id,
4102 MGMT_OP_START_SERVICE_DISCOVERY,
4103 MGMT_STATUS_NOT_POWERED,
4104 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004105 goto failed;
4106 }
4107
4108 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004109 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004110 err = mgmt_cmd_complete(sk, hdev->id,
4111 MGMT_OP_START_SERVICE_DISCOVERY,
4112 MGMT_STATUS_BUSY, &cp->type,
4113 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004114 goto failed;
4115 }
4116
4117 uuid_count = __le16_to_cpu(cp->uuid_count);
4118 if (uuid_count > max_uuid_count) {
4119 BT_ERR("service_discovery: too big uuid_count value %u",
4120 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004121 err = mgmt_cmd_complete(sk, hdev->id,
4122 MGMT_OP_START_SERVICE_DISCOVERY,
4123 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4124 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004125 goto failed;
4126 }
4127
4128 expected_len = sizeof(*cp) + uuid_count * 16;
4129 if (expected_len != len) {
4130 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4131 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004132 err = mgmt_cmd_complete(sk, hdev->id,
4133 MGMT_OP_START_SERVICE_DISCOVERY,
4134 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4135 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004136 goto failed;
4137 }
4138
4139 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004140 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004141 if (!cmd) {
4142 err = -ENOMEM;
4143 goto failed;
4144 }
4145
Johan Hedberg2922a942014-12-05 13:36:06 +02004146 cmd->cmd_complete = service_discovery_cmd_complete;
4147
Marcel Holtmann22078802014-12-05 11:45:22 +01004148 /* Clear the discovery filter first to free any previously
4149 * allocated memory for the UUID list.
4150 */
4151 hci_discovery_filter_clear(hdev);
4152
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004153 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004154 hdev->discovery.type = cp->type;
4155 hdev->discovery.rssi = cp->rssi;
4156 hdev->discovery.uuid_count = uuid_count;
4157
4158 if (uuid_count > 0) {
4159 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4160 GFP_KERNEL);
4161 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004162 err = mgmt_cmd_complete(sk, hdev->id,
4163 MGMT_OP_START_SERVICE_DISCOVERY,
4164 MGMT_STATUS_FAILED,
4165 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004166 mgmt_pending_remove(cmd);
4167 goto failed;
4168 }
4169 }
4170
4171 hci_req_init(&req, hdev);
4172
4173 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004174 err = mgmt_cmd_complete(sk, hdev->id,
4175 MGMT_OP_START_SERVICE_DISCOVERY,
4176 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004177 mgmt_pending_remove(cmd);
4178 goto failed;
4179 }
4180
4181 err = hci_req_run(&req, start_discovery_complete);
4182 if (err < 0) {
4183 mgmt_pending_remove(cmd);
4184 goto failed;
4185 }
4186
4187 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4188
4189failed:
4190 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004191 return err;
4192}
4193
Marcel Holtmann1904a852015-01-11 13:50:44 -08004194static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004195{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004196 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004197
Andre Guedes0e05bba2013-04-30 15:29:33 -03004198 BT_DBG("status %d", status);
4199
4200 hci_dev_lock(hdev);
4201
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004202 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4203 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004204 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004205 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004206 }
4207
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004208 if (!status)
4209 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004210
Andre Guedes0e05bba2013-04-30 15:29:33 -03004211 hci_dev_unlock(hdev);
4212}
4213
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004214static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004215 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004216{
Johan Hedbergd9306502012-02-20 23:25:18 +02004217 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004218 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004219 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004220 int err;
4221
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004222 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004223
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004224 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004225
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004226 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004227 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4228 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4229 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004230 goto unlock;
4231 }
4232
4233 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004234 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4235 MGMT_STATUS_INVALID_PARAMS,
4236 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004237 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004238 }
4239
Johan Hedberg2922a942014-12-05 13:36:06 +02004240 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004241 if (!cmd) {
4242 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004243 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004244 }
4245
Johan Hedberg2922a942014-12-05 13:36:06 +02004246 cmd->cmd_complete = generic_cmd_complete;
4247
Andre Guedes0e05bba2013-04-30 15:29:33 -03004248 hci_req_init(&req, hdev);
4249
Johan Hedberg21a60d32014-06-10 14:05:58 +03004250 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004251
Johan Hedberg21a60d32014-06-10 14:05:58 +03004252 err = hci_req_run(&req, stop_discovery_complete);
4253 if (!err) {
4254 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004255 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004256 }
4257
Johan Hedberg21a60d32014-06-10 14:05:58 +03004258 mgmt_pending_remove(cmd);
4259
4260 /* If no HCI commands were sent we're done */
4261 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004262 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4263 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004264 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4265 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004266
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004267unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004268 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004269 return err;
4270}
4271
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004272static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004273 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004274{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004275 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004276 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004277 int err;
4278
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004279 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004280
Johan Hedberg561aafb2012-01-04 13:31:59 +02004281 hci_dev_lock(hdev);
4282
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004283 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004284 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4285 MGMT_STATUS_FAILED, &cp->addr,
4286 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004287 goto failed;
4288 }
4289
Johan Hedberga198e7b2012-02-17 14:27:06 +02004290 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004291 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004292 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4293 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4294 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004295 goto failed;
4296 }
4297
4298 if (cp->name_known) {
4299 e->name_state = NAME_KNOWN;
4300 list_del(&e->list);
4301 } else {
4302 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004303 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004304 }
4305
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004306 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4307 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004308
4309failed:
4310 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004311 return err;
4312}
4313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004314static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004315 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004316{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004317 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004318 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004319 int err;
4320
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004321 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004322
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004323 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004324 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4325 MGMT_STATUS_INVALID_PARAMS,
4326 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004327
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004328 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004329
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004330 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4331 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004332 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004333 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004334 goto done;
4335 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004336
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004337 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4338 sk);
4339 status = MGMT_STATUS_SUCCESS;
4340
4341done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004342 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4343 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004344
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004345 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004346
4347 return err;
4348}
4349
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004350static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004351 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004352{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004353 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004354 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004355 int err;
4356
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004357 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004358
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004359 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004360 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4361 MGMT_STATUS_INVALID_PARAMS,
4362 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004363
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004364 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004365
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004366 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4367 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004368 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004369 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004370 goto done;
4371 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004372
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004373 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4374 sk);
4375 status = MGMT_STATUS_SUCCESS;
4376
4377done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004378 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4379 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004380
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004381 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004382
4383 return err;
4384}
4385
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004386static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4387 u16 len)
4388{
4389 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004390 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004391 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004392 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004393
4394 BT_DBG("%s", hdev->name);
4395
Szymon Jancc72d4b82012-03-16 16:02:57 +01004396 source = __le16_to_cpu(cp->source);
4397
4398 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004399 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4400 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004401
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004402 hci_dev_lock(hdev);
4403
Szymon Jancc72d4b82012-03-16 16:02:57 +01004404 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004405 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4406 hdev->devid_product = __le16_to_cpu(cp->product);
4407 hdev->devid_version = __le16_to_cpu(cp->version);
4408
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004409 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4410 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004411
Johan Hedberg890ea892013-03-15 17:06:52 -05004412 hci_req_init(&req, hdev);
4413 update_eir(&req);
4414 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004415
4416 hci_dev_unlock(hdev);
4417
4418 return err;
4419}
4420
Marcel Holtmann1904a852015-01-11 13:50:44 -08004421static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4422 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004423{
4424 struct cmd_lookup match = { NULL, hdev };
4425
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304426 hci_dev_lock(hdev);
4427
Johan Hedberg4375f102013-09-25 13:26:10 +03004428 if (status) {
4429 u8 mgmt_err = mgmt_status(status);
4430
4431 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4432 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304433 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004434 }
4435
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004436 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004437 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004438 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004439 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004440
Johan Hedberg4375f102013-09-25 13:26:10 +03004441 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4442 &match);
4443
4444 new_settings(hdev, match.sk);
4445
4446 if (match.sk)
4447 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304448
4449unlock:
4450 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004451}
4452
Marcel Holtmann21b51872013-10-10 09:47:53 -07004453static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4454 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004455{
4456 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004457 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004458 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004459 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004460 int err;
4461
4462 BT_DBG("request for %s", hdev->name);
4463
Johan Hedberge6fe7982013-10-02 15:45:22 +03004464 status = mgmt_le_support(hdev);
4465 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004466 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4467 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004468
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004469 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004470 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4471 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004472
4473 hci_dev_lock(hdev);
4474
4475 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004476
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004477 /* The following conditions are ones which mean that we should
4478 * not do any HCI communication but directly send a mgmt
4479 * response to user space (after toggling the flag if
4480 * necessary).
4481 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004482 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004483 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4484 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004485 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004486 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004487 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004488 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004489
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004490 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004491 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004492 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004493 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004494 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004495 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004496 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004497 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004498 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004499 }
4500
4501 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4502 if (err < 0)
4503 goto unlock;
4504
4505 if (changed)
4506 err = new_settings(hdev, sk);
4507
4508 goto unlock;
4509 }
4510
4511 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4512 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004513 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4514 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004515 goto unlock;
4516 }
4517
4518 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4519 if (!cmd) {
4520 err = -ENOMEM;
4521 goto unlock;
4522 }
4523
4524 hci_req_init(&req, hdev);
4525
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004526 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004527 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004528 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004529 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004530
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004531 if (val)
4532 enable_advertising(&req);
4533 else
4534 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004535
4536 err = hci_req_run(&req, set_advertising_complete);
4537 if (err < 0)
4538 mgmt_pending_remove(cmd);
4539
4540unlock:
4541 hci_dev_unlock(hdev);
4542 return err;
4543}
4544
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004545static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4546 void *data, u16 len)
4547{
4548 struct mgmt_cp_set_static_address *cp = data;
4549 int err;
4550
4551 BT_DBG("%s", hdev->name);
4552
Marcel Holtmann62af4442013-10-02 22:10:32 -07004553 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004554 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4555 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004556
4557 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004558 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4559 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004560
4561 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4562 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004563 return mgmt_cmd_status(sk, hdev->id,
4564 MGMT_OP_SET_STATIC_ADDRESS,
4565 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004566
4567 /* Two most significant bits shall be set */
4568 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004569 return mgmt_cmd_status(sk, hdev->id,
4570 MGMT_OP_SET_STATIC_ADDRESS,
4571 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004572 }
4573
4574 hci_dev_lock(hdev);
4575
4576 bacpy(&hdev->static_addr, &cp->bdaddr);
4577
Marcel Holtmann93690c22015-03-06 10:11:21 -08004578 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4579 if (err < 0)
4580 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004581
Marcel Holtmann93690c22015-03-06 10:11:21 -08004582 err = new_settings(hdev, sk);
4583
4584unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004585 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004586 return err;
4587}
4588
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004589static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4590 void *data, u16 len)
4591{
4592 struct mgmt_cp_set_scan_params *cp = data;
4593 __u16 interval, window;
4594 int err;
4595
4596 BT_DBG("%s", hdev->name);
4597
4598 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004599 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4600 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004601
4602 interval = __le16_to_cpu(cp->interval);
4603
4604 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004605 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4606 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004607
4608 window = __le16_to_cpu(cp->window);
4609
4610 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004611 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4612 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004613
Marcel Holtmann899e1072013-10-14 09:55:32 -07004614 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004615 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4616 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004617
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004618 hci_dev_lock(hdev);
4619
4620 hdev->le_scan_interval = interval;
4621 hdev->le_scan_window = window;
4622
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004623 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4624 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004625
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004626 /* If background scan is running, restart it so new parameters are
4627 * loaded.
4628 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004629 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004630 hdev->discovery.state == DISCOVERY_STOPPED) {
4631 struct hci_request req;
4632
4633 hci_req_init(&req, hdev);
4634
4635 hci_req_add_le_scan_disable(&req);
4636 hci_req_add_le_passive_scan(&req);
4637
4638 hci_req_run(&req, NULL);
4639 }
4640
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004641 hci_dev_unlock(hdev);
4642
4643 return err;
4644}
4645
Marcel Holtmann1904a852015-01-11 13:50:44 -08004646static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4647 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004648{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004649 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004650
4651 BT_DBG("status 0x%02x", status);
4652
4653 hci_dev_lock(hdev);
4654
4655 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4656 if (!cmd)
4657 goto unlock;
4658
4659 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004660 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4661 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004662 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004663 struct mgmt_mode *cp = cmd->param;
4664
4665 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004666 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004667 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004668 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004669
Johan Hedberg33e38b32013-03-15 17:07:05 -05004670 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4671 new_settings(hdev, cmd->sk);
4672 }
4673
4674 mgmt_pending_remove(cmd);
4675
4676unlock:
4677 hci_dev_unlock(hdev);
4678}
4679
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004680static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004681 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004682{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004683 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004684 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004685 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004686 int err;
4687
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004688 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004689
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004690 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004691 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004692 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4693 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004694
Johan Hedberga7e80f22013-01-09 16:05:19 +02004695 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004696 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4697 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004698
Antti Julkuf6422ec2011-06-22 13:11:56 +03004699 hci_dev_lock(hdev);
4700
Johan Hedberg05cbf292013-03-15 17:07:07 -05004701 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004702 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4703 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004704 goto unlock;
4705 }
4706
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004707 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004708 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4709 hdev);
4710 goto unlock;
4711 }
4712
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004713 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004714 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004715 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4716 hdev);
4717 new_settings(hdev, sk);
4718 goto unlock;
4719 }
4720
Johan Hedberg33e38b32013-03-15 17:07:05 -05004721 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4722 data, len);
4723 if (!cmd) {
4724 err = -ENOMEM;
4725 goto unlock;
4726 }
4727
4728 hci_req_init(&req, hdev);
4729
Johan Hedberg406d7802013-03-15 17:07:09 -05004730 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004731
4732 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004733 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004734 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4735 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004736 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004737 }
4738
Johan Hedberg33e38b32013-03-15 17:07:05 -05004739unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004740 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004741
Antti Julkuf6422ec2011-06-22 13:11:56 +03004742 return err;
4743}
4744
Marcel Holtmann1904a852015-01-11 13:50:44 -08004745static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004746{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004747 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004748
4749 BT_DBG("status 0x%02x", status);
4750
4751 hci_dev_lock(hdev);
4752
4753 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4754 if (!cmd)
4755 goto unlock;
4756
4757 if (status) {
4758 u8 mgmt_err = mgmt_status(status);
4759
4760 /* We need to restore the flag if related HCI commands
4761 * failed.
4762 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004763 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004764
Johan Hedberga69e8372015-03-06 21:08:53 +02004765 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004766 } else {
4767 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4768 new_settings(hdev, cmd->sk);
4769 }
4770
4771 mgmt_pending_remove(cmd);
4772
4773unlock:
4774 hci_dev_unlock(hdev);
4775}
4776
4777static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4778{
4779 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004780 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004781 struct hci_request req;
4782 int err;
4783
4784 BT_DBG("request for %s", hdev->name);
4785
4786 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004787 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4788 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004789
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004790 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004791 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4792 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004793
4794 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004795 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4796 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004797
4798 hci_dev_lock(hdev);
4799
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004800 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004801 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4802 goto unlock;
4803 }
4804
4805 if (!hdev_is_powered(hdev)) {
4806 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004807 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4808 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4809 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4810 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4811 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004812 }
4813
Marcel Holtmannce05d602015-03-13 02:11:03 -07004814 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004815
4816 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4817 if (err < 0)
4818 goto unlock;
4819
4820 err = new_settings(hdev, sk);
4821 goto unlock;
4822 }
4823
4824 /* Reject disabling when powered on */
4825 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004826 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4827 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004828 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004829 } else {
4830 /* When configuring a dual-mode controller to operate
4831 * with LE only and using a static address, then switching
4832 * BR/EDR back on is not allowed.
4833 *
4834 * Dual-mode controllers shall operate with the public
4835 * address as its identity address for BR/EDR and LE. So
4836 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004837 *
4838 * The same restrictions applies when secure connections
4839 * has been enabled. For BR/EDR this is a controller feature
4840 * while for LE it is a host stack feature. This means that
4841 * switching BR/EDR back on when secure connections has been
4842 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004843 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004844 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004845 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004846 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004847 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4848 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004849 goto unlock;
4850 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004851 }
4852
4853 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004854 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4855 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004856 goto unlock;
4857 }
4858
4859 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4860 if (!cmd) {
4861 err = -ENOMEM;
4862 goto unlock;
4863 }
4864
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004865 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004866 * generates the correct flags.
4867 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004868 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004869
4870 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004871
Johan Hedberg432df052014-08-01 11:13:31 +03004872 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004873 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004874
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004875 /* Since only the advertising data flags will change, there
4876 * is no need to update the scan response data.
4877 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004878 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004879
Johan Hedberg0663ca22013-10-02 13:43:14 +03004880 err = hci_req_run(&req, set_bredr_complete);
4881 if (err < 0)
4882 mgmt_pending_remove(cmd);
4883
4884unlock:
4885 hci_dev_unlock(hdev);
4886 return err;
4887}
4888
Johan Hedberga1443f52015-01-23 15:42:46 +02004889static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4890{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004891 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004892 struct mgmt_mode *cp;
4893
4894 BT_DBG("%s status %u", hdev->name, status);
4895
4896 hci_dev_lock(hdev);
4897
4898 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4899 if (!cmd)
4900 goto unlock;
4901
4902 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004903 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4904 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02004905 goto remove;
4906 }
4907
4908 cp = cmd->param;
4909
4910 switch (cp->val) {
4911 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004912 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
4913 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004914 break;
4915 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004916 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004917 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004918 break;
4919 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004920 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
4921 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02004922 break;
4923 }
4924
4925 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
4926 new_settings(hdev, cmd->sk);
4927
4928remove:
4929 mgmt_pending_remove(cmd);
4930unlock:
4931 hci_dev_unlock(hdev);
4932}
4933
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004934static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
4935 void *data, u16 len)
4936{
4937 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004938 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004939 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03004940 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004941 int err;
4942
4943 BT_DBG("request for %s", hdev->name);
4944
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004945 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004946 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004947 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4948 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004949
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004950 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02004951 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004952 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004953 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4954 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08004955
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004956 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004957 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004958 MGMT_STATUS_INVALID_PARAMS);
4959
4960 hci_dev_lock(hdev);
4961
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08004962 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004963 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004964 bool changed;
4965
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004966 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004967 changed = !hci_dev_test_and_set_flag(hdev,
4968 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004969 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004970 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004971 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004972 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004973 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004974 changed = hci_dev_test_and_clear_flag(hdev,
4975 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004976 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004977 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004978
4979 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
4980 if (err < 0)
4981 goto failed;
4982
4983 if (changed)
4984 err = new_settings(hdev, sk);
4985
4986 goto failed;
4987 }
4988
4989 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004990 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
4991 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004992 goto failed;
4993 }
4994
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08004995 val = !!cp->val;
4996
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004997 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
4998 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08004999 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5000 goto failed;
5001 }
5002
5003 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5004 if (!cmd) {
5005 err = -ENOMEM;
5006 goto failed;
5007 }
5008
Johan Hedberga1443f52015-01-23 15:42:46 +02005009 hci_req_init(&req, hdev);
5010 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5011 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005012 if (err < 0) {
5013 mgmt_pending_remove(cmd);
5014 goto failed;
5015 }
5016
5017failed:
5018 hci_dev_unlock(hdev);
5019 return err;
5020}
5021
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005022static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5023 void *data, u16 len)
5024{
5025 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005026 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005027 int err;
5028
5029 BT_DBG("request for %s", hdev->name);
5030
Johan Hedbergb97109792014-06-24 14:00:28 +03005031 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005032 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5033 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005034
5035 hci_dev_lock(hdev);
5036
5037 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005038 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005039 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005040 changed = hci_dev_test_and_clear_flag(hdev,
5041 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005042
Johan Hedbergb97109792014-06-24 14:00:28 +03005043 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005044 use_changed = !hci_dev_test_and_set_flag(hdev,
5045 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005046 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005047 use_changed = hci_dev_test_and_clear_flag(hdev,
5048 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005049
5050 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005051 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005052 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5053 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5054 sizeof(mode), &mode);
5055 }
5056
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005057 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5058 if (err < 0)
5059 goto unlock;
5060
5061 if (changed)
5062 err = new_settings(hdev, sk);
5063
5064unlock:
5065 hci_dev_unlock(hdev);
5066 return err;
5067}
5068
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005069static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5070 u16 len)
5071{
5072 struct mgmt_cp_set_privacy *cp = cp_data;
5073 bool changed;
5074 int err;
5075
5076 BT_DBG("request for %s", hdev->name);
5077
5078 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005079 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5080 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005081
5082 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005083 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5084 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005085
5086 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005087 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5088 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005089
5090 hci_dev_lock(hdev);
5091
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005092 /* If user space supports this command it is also expected to
5093 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5094 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005095 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005096
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005097 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005098 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005099 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005100 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005101 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005102 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005103 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005104 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005105 }
5106
5107 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5108 if (err < 0)
5109 goto unlock;
5110
5111 if (changed)
5112 err = new_settings(hdev, sk);
5113
5114unlock:
5115 hci_dev_unlock(hdev);
5116 return err;
5117}
5118
Johan Hedberg41edf162014-02-18 10:19:35 +02005119static bool irk_is_valid(struct mgmt_irk_info *irk)
5120{
5121 switch (irk->addr.type) {
5122 case BDADDR_LE_PUBLIC:
5123 return true;
5124
5125 case BDADDR_LE_RANDOM:
5126 /* Two most significant bits shall be set */
5127 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5128 return false;
5129 return true;
5130 }
5131
5132 return false;
5133}
5134
5135static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5136 u16 len)
5137{
5138 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005139 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5140 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005141 u16 irk_count, expected_len;
5142 int i, err;
5143
5144 BT_DBG("request for %s", hdev->name);
5145
5146 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005147 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5148 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005149
5150 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005151 if (irk_count > max_irk_count) {
5152 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005153 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5154 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005155 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005156
5157 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5158 if (expected_len != len) {
5159 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005160 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005161 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5162 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005163 }
5164
5165 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5166
5167 for (i = 0; i < irk_count; i++) {
5168 struct mgmt_irk_info *key = &cp->irks[i];
5169
5170 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005171 return mgmt_cmd_status(sk, hdev->id,
5172 MGMT_OP_LOAD_IRKS,
5173 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005174 }
5175
5176 hci_dev_lock(hdev);
5177
5178 hci_smp_irks_clear(hdev);
5179
5180 for (i = 0; i < irk_count; i++) {
5181 struct mgmt_irk_info *irk = &cp->irks[i];
5182 u8 addr_type;
5183
5184 if (irk->addr.type == BDADDR_LE_PUBLIC)
5185 addr_type = ADDR_LE_DEV_PUBLIC;
5186 else
5187 addr_type = ADDR_LE_DEV_RANDOM;
5188
5189 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5190 BDADDR_ANY);
5191 }
5192
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005193 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005194
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005195 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005196
5197 hci_dev_unlock(hdev);
5198
5199 return err;
5200}
5201
Johan Hedberg3f706b72013-01-20 14:27:16 +02005202static bool ltk_is_valid(struct mgmt_ltk_info *key)
5203{
5204 if (key->master != 0x00 && key->master != 0x01)
5205 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005206
5207 switch (key->addr.type) {
5208 case BDADDR_LE_PUBLIC:
5209 return true;
5210
5211 case BDADDR_LE_RANDOM:
5212 /* Two most significant bits shall be set */
5213 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5214 return false;
5215 return true;
5216 }
5217
5218 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005219}
5220
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005221static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005222 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005223{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005224 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005225 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5226 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005227 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005228 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005229
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005230 BT_DBG("request for %s", hdev->name);
5231
5232 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005233 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5234 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005235
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005236 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005237 if (key_count > max_key_count) {
5238 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005239 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5240 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005241 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005242
5243 expected_len = sizeof(*cp) + key_count *
5244 sizeof(struct mgmt_ltk_info);
5245 if (expected_len != len) {
5246 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005247 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5249 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005250 }
5251
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005252 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005253
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005254 for (i = 0; i < key_count; i++) {
5255 struct mgmt_ltk_info *key = &cp->keys[i];
5256
Johan Hedberg3f706b72013-01-20 14:27:16 +02005257 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005258 return mgmt_cmd_status(sk, hdev->id,
5259 MGMT_OP_LOAD_LONG_TERM_KEYS,
5260 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005261 }
5262
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005263 hci_dev_lock(hdev);
5264
5265 hci_smp_ltks_clear(hdev);
5266
5267 for (i = 0; i < key_count; i++) {
5268 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005269 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005270
5271 if (key->addr.type == BDADDR_LE_PUBLIC)
5272 addr_type = ADDR_LE_DEV_PUBLIC;
5273 else
5274 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005275
Johan Hedberg61b43352014-05-29 19:36:53 +03005276 switch (key->type) {
5277 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005278 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005279 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005280 break;
5281 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005282 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005283 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005284 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005285 case MGMT_LTK_P256_UNAUTH:
5286 authenticated = 0x00;
5287 type = SMP_LTK_P256;
5288 break;
5289 case MGMT_LTK_P256_AUTH:
5290 authenticated = 0x01;
5291 type = SMP_LTK_P256;
5292 break;
5293 case MGMT_LTK_P256_DEBUG:
5294 authenticated = 0x00;
5295 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005296 default:
5297 continue;
5298 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005299
Johan Hedberg35d70272014-02-19 14:57:47 +02005300 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005301 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005302 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005303 }
5304
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005305 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005306 NULL, 0);
5307
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005308 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005309
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005310 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005311}
5312
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005313static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005314{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005315 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005316 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005317 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005318
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005319 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005320
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005321 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005322 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005323 rp.tx_power = conn->tx_power;
5324 rp.max_tx_power = conn->max_tx_power;
5325 } else {
5326 rp.rssi = HCI_RSSI_INVALID;
5327 rp.tx_power = HCI_TX_POWER_INVALID;
5328 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005329 }
5330
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005331 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5332 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005333
5334 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005335 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005336
5337 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005338}
5339
Marcel Holtmann1904a852015-01-11 13:50:44 -08005340static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5341 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005342{
5343 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005344 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005345 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005346 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005347 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005348
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005349 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005350
5351 hci_dev_lock(hdev);
5352
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005353 /* Commands sent in request are either Read RSSI or Read Transmit Power
5354 * Level so we check which one was last sent to retrieve connection
5355 * handle. Both commands have handle as first parameter so it's safe to
5356 * cast data on the same command struct.
5357 *
5358 * First command sent is always Read RSSI and we fail only if it fails.
5359 * In other case we simply override error to indicate success as we
5360 * already remembered if TX power value is actually valid.
5361 */
5362 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5363 if (!cp) {
5364 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005365 status = MGMT_STATUS_SUCCESS;
5366 } else {
5367 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005368 }
5369
5370 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005371 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005372 goto unlock;
5373 }
5374
5375 handle = __le16_to_cpu(cp->handle);
5376 conn = hci_conn_hash_lookup_handle(hdev, handle);
5377 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005378 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005379 goto unlock;
5380 }
5381
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005382 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5383 if (!cmd)
5384 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005385
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005386 cmd->cmd_complete(cmd, status);
5387 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005388
5389unlock:
5390 hci_dev_unlock(hdev);
5391}
5392
5393static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5394 u16 len)
5395{
5396 struct mgmt_cp_get_conn_info *cp = data;
5397 struct mgmt_rp_get_conn_info rp;
5398 struct hci_conn *conn;
5399 unsigned long conn_info_age;
5400 int err = 0;
5401
5402 BT_DBG("%s", hdev->name);
5403
5404 memset(&rp, 0, sizeof(rp));
5405 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5406 rp.addr.type = cp->addr.type;
5407
5408 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005409 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5410 MGMT_STATUS_INVALID_PARAMS,
5411 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005412
5413 hci_dev_lock(hdev);
5414
5415 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005416 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5417 MGMT_STATUS_NOT_POWERED, &rp,
5418 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005419 goto unlock;
5420 }
5421
5422 if (cp->addr.type == BDADDR_BREDR)
5423 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5424 &cp->addr.bdaddr);
5425 else
5426 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5427
5428 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005429 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5430 MGMT_STATUS_NOT_CONNECTED, &rp,
5431 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005432 goto unlock;
5433 }
5434
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005435 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005436 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5437 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005438 goto unlock;
5439 }
5440
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005441 /* To avoid client trying to guess when to poll again for information we
5442 * calculate conn info age as random value between min/max set in hdev.
5443 */
5444 conn_info_age = hdev->conn_info_min_age +
5445 prandom_u32_max(hdev->conn_info_max_age -
5446 hdev->conn_info_min_age);
5447
5448 /* Query controller to refresh cached values if they are too old or were
5449 * never read.
5450 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005451 if (time_after(jiffies, conn->conn_info_timestamp +
5452 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005453 !conn->conn_info_timestamp) {
5454 struct hci_request req;
5455 struct hci_cp_read_tx_power req_txp_cp;
5456 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005457 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005458
5459 hci_req_init(&req, hdev);
5460 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5461 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5462 &req_rssi_cp);
5463
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005464 /* For LE links TX power does not change thus we don't need to
5465 * query for it once value is known.
5466 */
5467 if (!bdaddr_type_is_le(cp->addr.type) ||
5468 conn->tx_power == HCI_TX_POWER_INVALID) {
5469 req_txp_cp.handle = cpu_to_le16(conn->handle);
5470 req_txp_cp.type = 0x00;
5471 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5472 sizeof(req_txp_cp), &req_txp_cp);
5473 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005474
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005475 /* Max TX power needs to be read only once per connection */
5476 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5477 req_txp_cp.handle = cpu_to_le16(conn->handle);
5478 req_txp_cp.type = 0x01;
5479 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5480 sizeof(req_txp_cp), &req_txp_cp);
5481 }
5482
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005483 err = hci_req_run(&req, conn_info_refresh_complete);
5484 if (err < 0)
5485 goto unlock;
5486
5487 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5488 data, len);
5489 if (!cmd) {
5490 err = -ENOMEM;
5491 goto unlock;
5492 }
5493
5494 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005495 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005496 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005497
5498 conn->conn_info_timestamp = jiffies;
5499 } else {
5500 /* Cache is valid, just reply with values cached in hci_conn */
5501 rp.rssi = conn->rssi;
5502 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005503 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005504
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005505 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5506 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507 }
5508
5509unlock:
5510 hci_dev_unlock(hdev);
5511 return err;
5512}
5513
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005514static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005515{
5516 struct hci_conn *conn = cmd->user_data;
5517 struct mgmt_rp_get_clock_info rp;
5518 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005519 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005520
5521 memset(&rp, 0, sizeof(rp));
5522 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5523
5524 if (status)
5525 goto complete;
5526
5527 hdev = hci_dev_get(cmd->index);
5528 if (hdev) {
5529 rp.local_clock = cpu_to_le32(hdev->clock);
5530 hci_dev_put(hdev);
5531 }
5532
5533 if (conn) {
5534 rp.piconet_clock = cpu_to_le32(conn->clock);
5535 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5536 }
5537
5538complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005539 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5540 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005541
5542 if (conn) {
5543 hci_conn_drop(conn);
5544 hci_conn_put(conn);
5545 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005546
5547 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005548}
5549
Marcel Holtmann1904a852015-01-11 13:50:44 -08005550static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005551{
Johan Hedberg95868422014-06-28 17:54:07 +03005552 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005553 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005554 struct hci_conn *conn;
5555
5556 BT_DBG("%s status %u", hdev->name, status);
5557
5558 hci_dev_lock(hdev);
5559
5560 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5561 if (!hci_cp)
5562 goto unlock;
5563
5564 if (hci_cp->which) {
5565 u16 handle = __le16_to_cpu(hci_cp->handle);
5566 conn = hci_conn_hash_lookup_handle(hdev, handle);
5567 } else {
5568 conn = NULL;
5569 }
5570
5571 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5572 if (!cmd)
5573 goto unlock;
5574
Johan Hedberg69487372014-12-05 13:36:07 +02005575 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005576 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005577
5578unlock:
5579 hci_dev_unlock(hdev);
5580}
5581
5582static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5583 u16 len)
5584{
5585 struct mgmt_cp_get_clock_info *cp = data;
5586 struct mgmt_rp_get_clock_info rp;
5587 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005588 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005589 struct hci_request req;
5590 struct hci_conn *conn;
5591 int err;
5592
5593 BT_DBG("%s", hdev->name);
5594
5595 memset(&rp, 0, sizeof(rp));
5596 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5597 rp.addr.type = cp->addr.type;
5598
5599 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005600 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5601 MGMT_STATUS_INVALID_PARAMS,
5602 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005603
5604 hci_dev_lock(hdev);
5605
5606 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005607 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5608 MGMT_STATUS_NOT_POWERED, &rp,
5609 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005610 goto unlock;
5611 }
5612
5613 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5614 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5615 &cp->addr.bdaddr);
5616 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005617 err = mgmt_cmd_complete(sk, hdev->id,
5618 MGMT_OP_GET_CLOCK_INFO,
5619 MGMT_STATUS_NOT_CONNECTED,
5620 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005621 goto unlock;
5622 }
5623 } else {
5624 conn = NULL;
5625 }
5626
5627 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5628 if (!cmd) {
5629 err = -ENOMEM;
5630 goto unlock;
5631 }
5632
Johan Hedberg69487372014-12-05 13:36:07 +02005633 cmd->cmd_complete = clock_info_cmd_complete;
5634
Johan Hedberg95868422014-06-28 17:54:07 +03005635 hci_req_init(&req, hdev);
5636
5637 memset(&hci_cp, 0, sizeof(hci_cp));
5638 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5639
5640 if (conn) {
5641 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005642 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005643
5644 hci_cp.handle = cpu_to_le16(conn->handle);
5645 hci_cp.which = 0x01; /* Piconet clock */
5646 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5647 }
5648
5649 err = hci_req_run(&req, get_clock_info_complete);
5650 if (err < 0)
5651 mgmt_pending_remove(cmd);
5652
5653unlock:
5654 hci_dev_unlock(hdev);
5655 return err;
5656}
5657
Johan Hedberg5a154e62014-12-19 22:26:02 +02005658static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5659{
5660 struct hci_conn *conn;
5661
5662 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5663 if (!conn)
5664 return false;
5665
5666 if (conn->dst_type != type)
5667 return false;
5668
5669 if (conn->state != BT_CONNECTED)
5670 return false;
5671
5672 return true;
5673}
5674
5675/* This function requires the caller holds hdev->lock */
5676static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5677 u8 addr_type, u8 auto_connect)
5678{
5679 struct hci_dev *hdev = req->hdev;
5680 struct hci_conn_params *params;
5681
5682 params = hci_conn_params_add(hdev, addr, addr_type);
5683 if (!params)
5684 return -EIO;
5685
5686 if (params->auto_connect == auto_connect)
5687 return 0;
5688
5689 list_del_init(&params->action);
5690
5691 switch (auto_connect) {
5692 case HCI_AUTO_CONN_DISABLED:
5693 case HCI_AUTO_CONN_LINK_LOSS:
5694 __hci_update_background_scan(req);
5695 break;
5696 case HCI_AUTO_CONN_REPORT:
5697 list_add(&params->action, &hdev->pend_le_reports);
5698 __hci_update_background_scan(req);
5699 break;
5700 case HCI_AUTO_CONN_DIRECT:
5701 case HCI_AUTO_CONN_ALWAYS:
5702 if (!is_connected(hdev, addr, addr_type)) {
5703 list_add(&params->action, &hdev->pend_le_conns);
5704 __hci_update_background_scan(req);
5705 }
5706 break;
5707 }
5708
5709 params->auto_connect = auto_connect;
5710
5711 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5712 auto_connect);
5713
5714 return 0;
5715}
5716
Marcel Holtmann8afef092014-06-29 22:28:34 +02005717static void device_added(struct sock *sk, struct hci_dev *hdev,
5718 bdaddr_t *bdaddr, u8 type, u8 action)
5719{
5720 struct mgmt_ev_device_added ev;
5721
5722 bacpy(&ev.addr.bdaddr, bdaddr);
5723 ev.addr.type = type;
5724 ev.action = action;
5725
5726 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5727}
5728
Marcel Holtmann1904a852015-01-11 13:50:44 -08005729static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005730{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005731 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005732
5733 BT_DBG("status 0x%02x", status);
5734
5735 hci_dev_lock(hdev);
5736
5737 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5738 if (!cmd)
5739 goto unlock;
5740
5741 cmd->cmd_complete(cmd, mgmt_status(status));
5742 mgmt_pending_remove(cmd);
5743
5744unlock:
5745 hci_dev_unlock(hdev);
5746}
5747
Marcel Holtmann2faade52014-06-29 19:44:03 +02005748static int add_device(struct sock *sk, struct hci_dev *hdev,
5749 void *data, u16 len)
5750{
5751 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005752 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005753 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005754 u8 auto_conn, addr_type;
5755 int err;
5756
5757 BT_DBG("%s", hdev->name);
5758
Johan Hedberg66593582014-07-09 12:59:14 +03005759 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005760 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005761 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5762 MGMT_STATUS_INVALID_PARAMS,
5763 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005764
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005765 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005766 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5767 MGMT_STATUS_INVALID_PARAMS,
5768 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005769
Johan Hedberg5a154e62014-12-19 22:26:02 +02005770 hci_req_init(&req, hdev);
5771
Marcel Holtmann2faade52014-06-29 19:44:03 +02005772 hci_dev_lock(hdev);
5773
Johan Hedberg5a154e62014-12-19 22:26:02 +02005774 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5775 if (!cmd) {
5776 err = -ENOMEM;
5777 goto unlock;
5778 }
5779
5780 cmd->cmd_complete = addr_cmd_complete;
5781
Johan Hedberg66593582014-07-09 12:59:14 +03005782 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005783 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005784 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005785 err = cmd->cmd_complete(cmd,
5786 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005787 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005788 goto unlock;
5789 }
5790
5791 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5792 cp->addr.type);
5793 if (err)
5794 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005795
Johan Hedberg5a154e62014-12-19 22:26:02 +02005796 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005797
Johan Hedberg66593582014-07-09 12:59:14 +03005798 goto added;
5799 }
5800
Marcel Holtmann2faade52014-06-29 19:44:03 +02005801 if (cp->addr.type == BDADDR_LE_PUBLIC)
5802 addr_type = ADDR_LE_DEV_PUBLIC;
5803 else
5804 addr_type = ADDR_LE_DEV_RANDOM;
5805
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005806 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005807 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005808 else if (cp->action == 0x01)
5809 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005810 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005811 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005812
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005813 /* If the connection parameters don't exist for this device,
5814 * they will be created and configured with defaults.
5815 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005816 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005817 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005818 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005819 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005820 goto unlock;
5821 }
5822
Johan Hedberg66593582014-07-09 12:59:14 +03005823added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005824 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5825
Johan Hedberg5a154e62014-12-19 22:26:02 +02005826 err = hci_req_run(&req, add_device_complete);
5827 if (err < 0) {
5828 /* ENODATA means no HCI commands were needed (e.g. if
5829 * the adapter is powered off).
5830 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005831 if (err == -ENODATA)
5832 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005833 mgmt_pending_remove(cmd);
5834 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005835
5836unlock:
5837 hci_dev_unlock(hdev);
5838 return err;
5839}
5840
Marcel Holtmann8afef092014-06-29 22:28:34 +02005841static void device_removed(struct sock *sk, struct hci_dev *hdev,
5842 bdaddr_t *bdaddr, u8 type)
5843{
5844 struct mgmt_ev_device_removed ev;
5845
5846 bacpy(&ev.addr.bdaddr, bdaddr);
5847 ev.addr.type = type;
5848
5849 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5850}
5851
Marcel Holtmann1904a852015-01-11 13:50:44 -08005852static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005853{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005854 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005855
5856 BT_DBG("status 0x%02x", status);
5857
5858 hci_dev_lock(hdev);
5859
5860 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5861 if (!cmd)
5862 goto unlock;
5863
5864 cmd->cmd_complete(cmd, mgmt_status(status));
5865 mgmt_pending_remove(cmd);
5866
5867unlock:
5868 hci_dev_unlock(hdev);
5869}
5870
Marcel Holtmann2faade52014-06-29 19:44:03 +02005871static int remove_device(struct sock *sk, struct hci_dev *hdev,
5872 void *data, u16 len)
5873{
5874 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005875 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005876 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005877 int err;
5878
5879 BT_DBG("%s", hdev->name);
5880
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005881 hci_req_init(&req, hdev);
5882
Marcel Holtmann2faade52014-06-29 19:44:03 +02005883 hci_dev_lock(hdev);
5884
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005885 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5886 if (!cmd) {
5887 err = -ENOMEM;
5888 goto unlock;
5889 }
5890
5891 cmd->cmd_complete = addr_cmd_complete;
5892
Marcel Holtmann2faade52014-06-29 19:44:03 +02005893 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005894 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005895 u8 addr_type;
5896
Johan Hedberg66593582014-07-09 12:59:14 +03005897 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005898 err = cmd->cmd_complete(cmd,
5899 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005900 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005901 goto unlock;
5902 }
5903
Johan Hedberg66593582014-07-09 12:59:14 +03005904 if (cp->addr.type == BDADDR_BREDR) {
5905 err = hci_bdaddr_list_del(&hdev->whitelist,
5906 &cp->addr.bdaddr,
5907 cp->addr.type);
5908 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005909 err = cmd->cmd_complete(cmd,
5910 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005911 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005912 goto unlock;
5913 }
5914
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005915 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005916
Johan Hedberg66593582014-07-09 12:59:14 +03005917 device_removed(sk, hdev, &cp->addr.bdaddr,
5918 cp->addr.type);
5919 goto complete;
5920 }
5921
Marcel Holtmann2faade52014-06-29 19:44:03 +02005922 if (cp->addr.type == BDADDR_LE_PUBLIC)
5923 addr_type = ADDR_LE_DEV_PUBLIC;
5924 else
5925 addr_type = ADDR_LE_DEV_RANDOM;
5926
Johan Hedbergc71593d2014-07-02 17:37:28 +03005927 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
5928 addr_type);
5929 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005930 err = cmd->cmd_complete(cmd,
5931 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005932 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005933 goto unlock;
5934 }
5935
5936 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005937 err = cmd->cmd_complete(cmd,
5938 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005939 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005940 goto unlock;
5941 }
5942
Johan Hedbergd1dbf122014-07-04 16:17:23 +03005943 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03005944 list_del(&params->list);
5945 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005946 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02005947
5948 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005949 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03005950 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03005951 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03005952
Marcel Holtmann2faade52014-06-29 19:44:03 +02005953 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005954 err = cmd->cmd_complete(cmd,
5955 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005956 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005957 goto unlock;
5958 }
5959
Johan Hedberg66593582014-07-09 12:59:14 +03005960 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
5961 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
5962 list_del(&b->list);
5963 kfree(b);
5964 }
5965
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005966 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005967
Johan Hedberg19de0822014-07-06 13:06:51 +03005968 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
5969 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
5970 continue;
5971 device_removed(sk, hdev, &p->addr, p->addr_type);
5972 list_del(&p->action);
5973 list_del(&p->list);
5974 kfree(p);
5975 }
5976
5977 BT_DBG("All LE connection parameters were removed");
5978
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005979 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005980 }
5981
Johan Hedberg66593582014-07-09 12:59:14 +03005982complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005983 err = hci_req_run(&req, remove_device_complete);
5984 if (err < 0) {
5985 /* ENODATA means no HCI commands were needed (e.g. if
5986 * the adapter is powered off).
5987 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005988 if (err == -ENODATA)
5989 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005990 mgmt_pending_remove(cmd);
5991 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005992
5993unlock:
5994 hci_dev_unlock(hdev);
5995 return err;
5996}
5997
Johan Hedberga26f3dc2014-07-02 17:37:29 +03005998static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5999 u16 len)
6000{
6001 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006002 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6003 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006004 u16 param_count, expected_len;
6005 int i;
6006
6007 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006008 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6009 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006010
6011 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006012 if (param_count > max_param_count) {
6013 BT_ERR("load_conn_param: too big param_count value %u",
6014 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006015 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6016 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006017 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006018
6019 expected_len = sizeof(*cp) + param_count *
6020 sizeof(struct mgmt_conn_param);
6021 if (expected_len != len) {
6022 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6023 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006024 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6025 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006026 }
6027
6028 BT_DBG("%s param_count %u", hdev->name, param_count);
6029
6030 hci_dev_lock(hdev);
6031
6032 hci_conn_params_clear_disabled(hdev);
6033
6034 for (i = 0; i < param_count; i++) {
6035 struct mgmt_conn_param *param = &cp->params[i];
6036 struct hci_conn_params *hci_param;
6037 u16 min, max, latency, timeout;
6038 u8 addr_type;
6039
6040 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6041 param->addr.type);
6042
6043 if (param->addr.type == BDADDR_LE_PUBLIC) {
6044 addr_type = ADDR_LE_DEV_PUBLIC;
6045 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6046 addr_type = ADDR_LE_DEV_RANDOM;
6047 } else {
6048 BT_ERR("Ignoring invalid connection parameters");
6049 continue;
6050 }
6051
6052 min = le16_to_cpu(param->min_interval);
6053 max = le16_to_cpu(param->max_interval);
6054 latency = le16_to_cpu(param->latency);
6055 timeout = le16_to_cpu(param->timeout);
6056
6057 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6058 min, max, latency, timeout);
6059
6060 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6061 BT_ERR("Ignoring invalid connection parameters");
6062 continue;
6063 }
6064
6065 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6066 addr_type);
6067 if (!hci_param) {
6068 BT_ERR("Failed to add connection parameters");
6069 continue;
6070 }
6071
6072 hci_param->conn_min_interval = min;
6073 hci_param->conn_max_interval = max;
6074 hci_param->conn_latency = latency;
6075 hci_param->supervision_timeout = timeout;
6076 }
6077
6078 hci_dev_unlock(hdev);
6079
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006080 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6081 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006082}
6083
Marcel Holtmanndbece372014-07-04 18:11:55 +02006084static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6085 void *data, u16 len)
6086{
6087 struct mgmt_cp_set_external_config *cp = data;
6088 bool changed;
6089 int err;
6090
6091 BT_DBG("%s", hdev->name);
6092
6093 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006094 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6095 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006096
6097 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006098 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6099 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006100
6101 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006102 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6103 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006104
6105 hci_dev_lock(hdev);
6106
6107 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006108 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006109 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006110 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006111
6112 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6113 if (err < 0)
6114 goto unlock;
6115
6116 if (!changed)
6117 goto unlock;
6118
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006119 err = new_options(hdev, sk);
6120
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006121 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006122 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006123
Marcel Holtmann516018a2015-03-13 02:11:04 -07006124 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006125 hci_dev_set_flag(hdev, HCI_CONFIG);
6126 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006127
6128 queue_work(hdev->req_workqueue, &hdev->power_on);
6129 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006130 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006131 mgmt_index_added(hdev);
6132 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006133 }
6134
6135unlock:
6136 hci_dev_unlock(hdev);
6137 return err;
6138}
6139
Marcel Holtmann9713c172014-07-06 12:11:15 +02006140static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6141 void *data, u16 len)
6142{
6143 struct mgmt_cp_set_public_address *cp = data;
6144 bool changed;
6145 int err;
6146
6147 BT_DBG("%s", hdev->name);
6148
6149 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006150 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6151 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006152
6153 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006154 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6155 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006156
6157 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006158 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6159 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006160
6161 hci_dev_lock(hdev);
6162
6163 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6164 bacpy(&hdev->public_addr, &cp->bdaddr);
6165
6166 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6167 if (err < 0)
6168 goto unlock;
6169
6170 if (!changed)
6171 goto unlock;
6172
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006173 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006174 err = new_options(hdev, sk);
6175
6176 if (is_configured(hdev)) {
6177 mgmt_index_removed(hdev);
6178
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006179 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006180
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006181 hci_dev_set_flag(hdev, HCI_CONFIG);
6182 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006183
6184 queue_work(hdev->req_workqueue, &hdev->power_on);
6185 }
6186
6187unlock:
6188 hci_dev_unlock(hdev);
6189 return err;
6190}
6191
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006192static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006193 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006194 { read_version, MGMT_READ_VERSION_SIZE,
6195 HCI_MGMT_NO_HDEV },
6196 { read_commands, MGMT_READ_COMMANDS_SIZE,
6197 HCI_MGMT_NO_HDEV },
6198 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
6199 HCI_MGMT_NO_HDEV },
6200 { read_controller_info, MGMT_READ_INFO_SIZE, 0 },
6201 { set_powered, MGMT_SETTING_SIZE, 0 },
6202 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE, 0 },
6203 { set_connectable, MGMT_SETTING_SIZE, 0 },
6204 { set_fast_connectable, MGMT_SETTING_SIZE, 0 },
6205 { set_bondable, MGMT_SETTING_SIZE, 0 },
6206 { set_link_security, MGMT_SETTING_SIZE, 0 },
6207 { set_ssp, MGMT_SETTING_SIZE, 0 },
6208 { set_hs, MGMT_SETTING_SIZE, 0 },
6209 { set_le, MGMT_SETTING_SIZE, 0 },
6210 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE, 0 },
6211 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE, 0 },
6212 { add_uuid, MGMT_ADD_UUID_SIZE, 0 },
6213 { remove_uuid, MGMT_REMOVE_UUID_SIZE, 0 },
6214 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6215 HCI_MGMT_VAR_LEN },
6216 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6217 HCI_MGMT_VAR_LEN },
6218 { disconnect, MGMT_DISCONNECT_SIZE, 0 },
6219 { get_connections, MGMT_GET_CONNECTIONS_SIZE, 0 },
6220 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE, 0 },
6221 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE, 0 },
6222 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE, 0 },
6223 { pair_device, MGMT_PAIR_DEVICE_SIZE, 0 },
6224 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE, 0 },
6225 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE, 0 },
6226 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE, 0 },
6227 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE, 0 },
6228 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE, 0 },
6229 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE, 0 },
6230 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6231 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6232 HCI_MGMT_VAR_LEN },
6233 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE, 0 },
6234 { start_discovery, MGMT_START_DISCOVERY_SIZE, 0 },
6235 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE, 0 },
6236 { confirm_name, MGMT_CONFIRM_NAME_SIZE, 0 },
6237 { block_device, MGMT_BLOCK_DEVICE_SIZE, 0 },
6238 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE, 0 },
6239 { set_device_id, MGMT_SET_DEVICE_ID_SIZE, 0 },
6240 { set_advertising, MGMT_SETTING_SIZE, 0 },
6241 { set_bredr, MGMT_SETTING_SIZE, 0 },
6242 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE, 0 },
6243 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE, 0 },
6244 { set_secure_conn, MGMT_SETTING_SIZE, 0 },
6245 { set_debug_keys, MGMT_SETTING_SIZE, 0 },
6246 { set_privacy, MGMT_SET_PRIVACY_SIZE, 0 },
6247 { load_irks, MGMT_LOAD_IRKS_SIZE,
6248 HCI_MGMT_VAR_LEN },
6249 { get_conn_info, MGMT_GET_CONN_INFO_SIZE, 0 },
6250 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE, 0 },
6251 { add_device, MGMT_ADD_DEVICE_SIZE, 0 },
6252 { remove_device, MGMT_REMOVE_DEVICE_SIZE, 0 },
6253 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6254 HCI_MGMT_VAR_LEN },
6255 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
6256 HCI_MGMT_NO_HDEV },
6257 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
6258 HCI_MGMT_UNCONFIGURED },
6259 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6260 HCI_MGMT_UNCONFIGURED },
6261 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6262 HCI_MGMT_UNCONFIGURED },
6263 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6264 HCI_MGMT_VAR_LEN },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006265};
6266
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006267int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6268 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006269{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006270 void *buf;
6271 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006272 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006273 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006274 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006275 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006276 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006277 int err;
6278
6279 BT_DBG("got %zu bytes", msglen);
6280
6281 if (msglen < sizeof(*hdr))
6282 return -EINVAL;
6283
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006284 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006285 if (!buf)
6286 return -ENOMEM;
6287
Al Viro6ce8e9c2014-04-06 21:25:44 -04006288 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006289 err = -EFAULT;
6290 goto done;
6291 }
6292
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006293 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006294 opcode = __le16_to_cpu(hdr->opcode);
6295 index = __le16_to_cpu(hdr->index);
6296 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006297
6298 if (len != msglen - sizeof(*hdr)) {
6299 err = -EINVAL;
6300 goto done;
6301 }
6302
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006303 if (opcode >= chan->handler_count ||
6304 chan->handlers[opcode].func == NULL) {
6305 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006306 err = mgmt_cmd_status(sk, index, opcode,
6307 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006308 goto done;
6309 }
6310
6311 handler = &chan->handlers[opcode];
6312
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006313 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006314 hdev = hci_dev_get(index);
6315 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006316 err = mgmt_cmd_status(sk, index, opcode,
6317 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006318 goto done;
6319 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006320
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006321 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6322 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6323 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006324 err = mgmt_cmd_status(sk, index, opcode,
6325 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006326 goto done;
6327 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006328
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006329 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006330 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006331 err = mgmt_cmd_status(sk, index, opcode,
6332 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006333 goto done;
6334 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006335 }
6336
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006337 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6338 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006339 err = mgmt_cmd_status(sk, index, opcode,
6340 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006341 goto done;
6342 }
6343
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006344 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6345 if ((var_len && len < handler->data_len) ||
6346 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006347 err = mgmt_cmd_status(sk, index, opcode,
6348 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006349 goto done;
6350 }
6351
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006352 if (hdev)
6353 mgmt_init_hdev(sk, hdev);
6354
6355 cp = buf + sizeof(*hdr);
6356
Johan Hedbergbe22b542012-03-01 22:24:41 +02006357 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006358 if (err < 0)
6359 goto done;
6360
Johan Hedberg03811012010-12-08 00:21:06 +02006361 err = msglen;
6362
6363done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006364 if (hdev)
6365 hci_dev_put(hdev);
6366
Johan Hedberg03811012010-12-08 00:21:06 +02006367 kfree(buf);
6368 return err;
6369}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006370
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006371void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006372{
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006373
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006374 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6375 return;
6376
Marcel Holtmannf9207332015-03-14 19:27:55 -07006377 switch (hdev->dev_type) {
6378 case HCI_BREDR:
6379 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6380 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6381 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
6382 } else {
6383 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6384 HCI_MGMT_INDEX_EVENTS);
6385 }
6386 break;
6387 }
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006388}
6389
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006390void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006391{
Johan Hedberg5f159032012-03-02 03:13:19 +02006392 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006393
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006394 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6395 return;
6396
Marcel Holtmannf9207332015-03-14 19:27:55 -07006397 switch (hdev->dev_type) {
6398 case HCI_BREDR:
6399 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006400
Marcel Holtmannf9207332015-03-14 19:27:55 -07006401 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6402 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
6403 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
6404 } else {
6405 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
6406 HCI_MGMT_INDEX_EVENTS);
6407 }
6408 break;
6409 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006410}
6411
Andre Guedes6046dc32014-02-26 20:21:51 -03006412/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006413static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006414{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006415 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006416 struct hci_conn_params *p;
6417
6418 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006419 /* Needed for AUTO_OFF case where might not "really"
6420 * have been powered off.
6421 */
6422 list_del_init(&p->action);
6423
6424 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006425 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006426 case HCI_AUTO_CONN_ALWAYS:
6427 list_add(&p->action, &hdev->pend_le_conns);
6428 break;
6429 case HCI_AUTO_CONN_REPORT:
6430 list_add(&p->action, &hdev->pend_le_reports);
6431 break;
6432 default:
6433 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006434 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006435 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006436
Johan Hedberg2cf22212014-12-19 22:26:00 +02006437 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006438}
6439
Marcel Holtmann1904a852015-01-11 13:50:44 -08006440static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006441{
6442 struct cmd_lookup match = { NULL, hdev };
6443
6444 BT_DBG("status 0x%02x", status);
6445
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006446 if (!status) {
6447 /* Register the available SMP channels (BR/EDR and LE) only
6448 * when successfully powering on the controller. This late
6449 * registration is required so that LE SMP can clearly
6450 * decide if the public address or static address is used.
6451 */
6452 smp_register(hdev);
6453 }
6454
Johan Hedberg229ab392013-03-15 17:06:53 -05006455 hci_dev_lock(hdev);
6456
6457 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6458
6459 new_settings(hdev, match.sk);
6460
6461 hci_dev_unlock(hdev);
6462
6463 if (match.sk)
6464 sock_put(match.sk);
6465}
6466
Johan Hedberg70da6242013-03-15 17:06:51 -05006467static int powered_update_hci(struct hci_dev *hdev)
6468{
Johan Hedberg890ea892013-03-15 17:06:52 -05006469 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006470 u8 link_sec;
6471
Johan Hedberg890ea892013-03-15 17:06:52 -05006472 hci_req_init(&req, hdev);
6473
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006474 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006475 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006476 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006477
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006478 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006479
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006480 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6481 u8 support = 0x01;
6482
6483 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6484 sizeof(support), &support);
6485 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006486 }
6487
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006488 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006489 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006490 struct hci_cp_write_le_host_supported cp;
6491
Marcel Holtmann32226e42014-07-24 20:04:16 +02006492 cp.le = 0x01;
6493 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006494
6495 /* Check first if we already have the right
6496 * host state (host features set)
6497 */
6498 if (cp.le != lmp_host_le_capable(hdev) ||
6499 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006500 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6501 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006502 }
6503
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006504 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006505 /* Make sure the controller has a good default for
6506 * advertising data. This also applies to the case
6507 * where BR/EDR was toggled during the AUTO_OFF phase.
6508 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006509 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006510 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006511 update_scan_rsp_data(&req);
6512 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006513
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006514 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006515 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006516
6517 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006518 }
6519
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006520 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006521 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006522 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6523 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006524
6525 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006526 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006527 write_fast_connectable(&req, true);
6528 else
6529 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006530 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006531 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006532 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006533 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006534 }
6535
Johan Hedberg229ab392013-03-15 17:06:53 -05006536 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006537}
6538
Johan Hedberg744cf192011-11-08 20:40:14 +02006539int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006540{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006541 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006542 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006543 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006544
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006545 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006546 return 0;
6547
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006548 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006549 if (powered_update_hci(hdev) == 0)
6550 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006551
Johan Hedberg229ab392013-03-15 17:06:53 -05006552 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6553 &match);
6554 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006555 }
6556
Johan Hedberg229ab392013-03-15 17:06:53 -05006557 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006558
6559 /* If the power off is because of hdev unregistration let
6560 * use the appropriate INVALID_INDEX status. Otherwise use
6561 * NOT_POWERED. We cover both scenarios here since later in
6562 * mgmt_index_removed() any hci_conn callbacks will have already
6563 * been triggered, potentially causing misleading DISCONNECTED
6564 * status responses.
6565 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006566 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006567 status = MGMT_STATUS_INVALID_INDEX;
6568 else
6569 status = MGMT_STATUS_NOT_POWERED;
6570
6571 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006572
6573 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
6574 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6575 zero_cod, sizeof(zero_cod), NULL);
6576
6577new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006578 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006579
6580 if (match.sk)
6581 sock_put(match.sk);
6582
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006583 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006584}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006585
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006586void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006587{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006588 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006589 u8 status;
6590
6591 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6592 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006593 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006594
6595 if (err == -ERFKILL)
6596 status = MGMT_STATUS_RFKILLED;
6597 else
6598 status = MGMT_STATUS_FAILED;
6599
Johan Hedberga69e8372015-03-06 21:08:53 +02006600 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006601
6602 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006603}
6604
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006605void mgmt_discoverable_timeout(struct hci_dev *hdev)
6606{
6607 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006608
6609 hci_dev_lock(hdev);
6610
6611 /* When discoverable timeout triggers, then just make sure
6612 * the limited discoverable flag is cleared. Even in the case
6613 * of a timeout triggered from general discoverable, it is
6614 * safe to unconditionally clear the flag.
6615 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006616 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
6617 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006618
6619 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006620 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006621 u8 scan = SCAN_PAGE;
6622 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6623 sizeof(scan), &scan);
6624 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006625 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006626 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006627 hci_req_run(&req, NULL);
6628
6629 hdev->discov_timeout = 0;
6630
Johan Hedberg9a43e252013-10-20 19:00:07 +03006631 new_settings(hdev, NULL);
6632
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006633 hci_dev_unlock(hdev);
6634}
6635
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006636void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6637 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006638{
Johan Hedberg86742e12011-11-07 23:13:38 +02006639 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006640
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006641 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006642
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006643 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006644 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006645 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006646 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006647 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006648 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006649
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006650 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006651}
Johan Hedbergf7520542011-01-20 12:34:39 +02006652
Johan Hedbergd7b25452014-05-23 13:19:53 +03006653static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6654{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006655 switch (ltk->type) {
6656 case SMP_LTK:
6657 case SMP_LTK_SLAVE:
6658 if (ltk->authenticated)
6659 return MGMT_LTK_AUTHENTICATED;
6660 return MGMT_LTK_UNAUTHENTICATED;
6661 case SMP_LTK_P256:
6662 if (ltk->authenticated)
6663 return MGMT_LTK_P256_AUTH;
6664 return MGMT_LTK_P256_UNAUTH;
6665 case SMP_LTK_P256_DEBUG:
6666 return MGMT_LTK_P256_DEBUG;
6667 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006668
6669 return MGMT_LTK_UNAUTHENTICATED;
6670}
6671
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006672void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006673{
6674 struct mgmt_ev_new_long_term_key ev;
6675
6676 memset(&ev, 0, sizeof(ev));
6677
Marcel Holtmann5192d302014-02-19 17:11:58 -08006678 /* Devices using resolvable or non-resolvable random addresses
6679 * without providing an indentity resolving key don't require
6680 * to store long term keys. Their addresses will change the
6681 * next time around.
6682 *
6683 * Only when a remote device provides an identity address
6684 * make sure the long term key is stored. If the remote
6685 * identity is known, the long term keys are internally
6686 * mapped to the identity address. So allow static random
6687 * and public addresses here.
6688 */
Johan Hedbergba74b662014-02-19 14:57:45 +02006689 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6690 (key->bdaddr.b[5] & 0xc0) != 0xc0)
6691 ev.store_hint = 0x00;
6692 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006693 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02006694
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006695 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006696 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03006697 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006698 ev.key.enc_size = key->enc_size;
6699 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08006700 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006701
Johan Hedberg2ceba532014-06-16 19:25:16 +03006702 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006703 ev.key.master = 1;
6704
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006705 memcpy(ev.key.val, key->val, sizeof(key->val));
6706
Marcel Holtmann083368f2013-10-15 14:26:29 -07006707 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006708}
6709
Johan Hedberg95fbac82014-02-19 15:18:31 +02006710void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
6711{
6712 struct mgmt_ev_new_irk ev;
6713
6714 memset(&ev, 0, sizeof(ev));
6715
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08006716 /* For identity resolving keys from devices that are already
6717 * using a public address or static random address, do not
6718 * ask for storing this key. The identity resolving key really
6719 * is only mandatory for devices using resovlable random
6720 * addresses.
6721 *
6722 * Storing all identity resolving keys has the downside that
6723 * they will be also loaded on next boot of they system. More
6724 * identity resolving keys, means more time during scanning is
6725 * needed to actually resolve these addresses.
6726 */
6727 if (bacmp(&irk->rpa, BDADDR_ANY))
6728 ev.store_hint = 0x01;
6729 else
6730 ev.store_hint = 0x00;
6731
Johan Hedberg95fbac82014-02-19 15:18:31 +02006732 bacpy(&ev.rpa, &irk->rpa);
6733 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
6734 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
6735 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
6736
6737 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
6738}
6739
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006740void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
6741 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006742{
6743 struct mgmt_ev_new_csrk ev;
6744
6745 memset(&ev, 0, sizeof(ev));
6746
6747 /* Devices using resolvable or non-resolvable random addresses
6748 * without providing an indentity resolving key don't require
6749 * to store signature resolving keys. Their addresses will change
6750 * the next time around.
6751 *
6752 * Only when a remote device provides an identity address
6753 * make sure the signature resolving key is stored. So allow
6754 * static random and public addresses here.
6755 */
6756 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
6757 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
6758 ev.store_hint = 0x00;
6759 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006760 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006761
6762 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
6763 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02006764 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07006765 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
6766
6767 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
6768}
6769
Andre Guedesffb5a8272014-07-01 18:10:11 -03006770void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03006771 u8 bdaddr_type, u8 store_hint, u16 min_interval,
6772 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03006773{
6774 struct mgmt_ev_new_conn_param ev;
6775
Johan Hedbergc103aea2014-07-02 17:37:34 +03006776 if (!hci_is_identity_address(bdaddr, bdaddr_type))
6777 return;
6778
Andre Guedesffb5a8272014-07-01 18:10:11 -03006779 memset(&ev, 0, sizeof(ev));
6780 bacpy(&ev.addr.bdaddr, bdaddr);
6781 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03006782 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03006783 ev.min_interval = cpu_to_le16(min_interval);
6784 ev.max_interval = cpu_to_le16(max_interval);
6785 ev.latency = cpu_to_le16(latency);
6786 ev.timeout = cpu_to_le16(timeout);
6787
6788 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
6789}
6790
Marcel Holtmann94933992013-10-15 10:26:39 -07006791static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6792 u8 data_len)
6793{
6794 eir[eir_len++] = sizeof(type) + data_len;
6795 eir[eir_len++] = type;
6796 memcpy(&eir[eir_len], data, data_len);
6797 eir_len += data_len;
6798
6799 return eir_len;
6800}
6801
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006802void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
6803 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02006804{
Johan Hedbergb644ba32012-01-17 21:48:47 +02006805 char buf[512];
6806 struct mgmt_ev_device_connected *ev = (void *) buf;
6807 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02006808
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00006809 bacpy(&ev->addr.bdaddr, &conn->dst);
6810 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02006811
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02006812 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02006813
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006814 /* We must ensure that the EIR Data fields are ordered and
6815 * unique. Keep it simple for now and avoid the problem by not
6816 * adding any BR/EDR data to the LE adv.
6817 */
6818 if (conn->le_adv_data_len > 0) {
6819 memcpy(&ev->eir[eir_len],
6820 conn->le_adv_data, conn->le_adv_data_len);
6821 eir_len = conn->le_adv_data_len;
6822 } else {
6823 if (name_len > 0)
6824 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
6825 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006826
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00006827 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00006828 eir_len = eir_append_data(ev->eir, eir_len,
6829 EIR_CLASS_OF_DEV,
6830 conn->dev_class, 3);
6831 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02006832
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02006833 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02006834
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07006835 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
6836 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02006837}
6838
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006839static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006840{
Johan Hedberg8962ee72011-01-20 12:40:27 +02006841 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006842
Johan Hedbergf5818c22014-12-05 13:36:02 +02006843 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006844
6845 *sk = cmd->sk;
6846 sock_hold(*sk);
6847
Johan Hedberga664b5b2011-02-19 12:06:02 -03006848 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006849}
6850
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006851static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02006852{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006853 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02006854 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02006855
Johan Hedbergb1078ad2012-02-09 17:21:16 +02006856 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
6857
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02006858 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02006859 mgmt_pending_remove(cmd);
6860}
6861
Johan Hedberg84c61d92014-08-01 11:13:30 +03006862bool mgmt_powering_down(struct hci_dev *hdev)
6863{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006864 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03006865 struct mgmt_mode *cp;
6866
6867 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6868 if (!cmd)
6869 return false;
6870
6871 cp = cmd->param;
6872 if (!cp->val)
6873 return true;
6874
6875 return false;
6876}
6877
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006878void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006879 u8 link_type, u8 addr_type, u8 reason,
6880 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02006881{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006882 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006883 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006884
Johan Hedberg84c61d92014-08-01 11:13:30 +03006885 /* The connection is still in hci_conn_hash so test for 1
6886 * instead of 0 to know if this is the last one.
6887 */
6888 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6889 cancel_delayed_work(&hdev->power_off);
6890 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02006891 }
6892
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02006893 if (!mgmt_connected)
6894 return;
6895
Andre Guedes57eb7762013-10-30 19:01:41 -03006896 if (link_type != ACL_LINK && link_type != LE_LINK)
6897 return;
6898
Johan Hedberg744cf192011-11-08 20:40:14 +02006899 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02006900
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02006901 bacpy(&ev.addr.bdaddr, bdaddr);
6902 ev.addr.type = link_to_bdaddr(link_type, addr_type);
6903 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02006904
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07006905 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006906
6907 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01006908 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006909
Johan Hedberg124f6e32012-02-09 13:50:12 +02006910 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006911 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006912}
6913
Marcel Holtmann78929242013-10-06 23:55:47 -07006914void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
6915 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02006916{
Andre Guedes3655bba2013-10-30 19:01:40 -03006917 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
6918 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006919 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006920
Jefferson Delfes36a75f12012-09-18 13:36:54 -04006921 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
6922 hdev);
6923
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006924 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02006925 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07006926 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02006927
Andre Guedes3655bba2013-10-30 19:01:40 -03006928 cp = cmd->param;
6929
6930 if (bacmp(bdaddr, &cp->addr.bdaddr))
6931 return;
6932
6933 if (cp->addr.type != bdaddr_type)
6934 return;
6935
Johan Hedbergf5818c22014-12-05 13:36:02 +02006936 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006937 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02006938}
Johan Hedberg17d5c042011-01-22 06:09:08 +02006939
Marcel Holtmann445608d2013-10-06 23:55:48 -07006940void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
6941 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02006942{
6943 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02006944
Johan Hedberg84c61d92014-08-01 11:13:30 +03006945 /* The connection is still in hci_conn_hash so test for 1
6946 * instead of 0 to know if this is the last one.
6947 */
6948 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
6949 cancel_delayed_work(&hdev->power_off);
6950 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02006951 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02006952
Johan Hedberg4c659c32011-11-07 23:13:39 +02006953 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03006954 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02006955 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006956
Marcel Holtmann445608d2013-10-06 23:55:48 -07006957 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02006958}
Johan Hedberg980e1a52011-01-22 06:10:07 +02006959
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006960void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006961{
6962 struct mgmt_ev_pin_code_request ev;
6963
Johan Hedbergd8457692012-02-17 14:24:57 +02006964 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006965 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02006966 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006967
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07006968 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006969}
6970
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006971void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6972 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006973{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006974 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006975
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006976 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006977 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07006978 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006979
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006980 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006981 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006982}
6983
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006984void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
6985 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02006986{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006987 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006988
Johan Hedberg2e58ef32011-11-08 20:40:15 +02006989 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006990 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07006991 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02006992
Johan Hedberg7776d1d2014-12-05 13:36:03 +02006993 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03006994 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02006995}
Johan Hedberga5c29682011-02-19 12:05:57 -03006996
Johan Hedberg744cf192011-11-08 20:40:14 +02006997int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02006998 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03006999 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007000{
7001 struct mgmt_ev_user_confirm_request ev;
7002
Johan Hedberg744cf192011-11-08 20:40:14 +02007003 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007004
Johan Hedberg272d90d2012-02-09 15:26:12 +02007005 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007006 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007007 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007008 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007009
Johan Hedberg744cf192011-11-08 20:40:14 +02007010 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007011 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007012}
7013
Johan Hedberg272d90d2012-02-09 15:26:12 +02007014int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007015 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007016{
7017 struct mgmt_ev_user_passkey_request ev;
7018
7019 BT_DBG("%s", hdev->name);
7020
Johan Hedberg272d90d2012-02-09 15:26:12 +02007021 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007022 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007023
7024 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007025 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007026}
7027
Brian Gix0df4c182011-11-16 13:53:13 -08007028static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007029 u8 link_type, u8 addr_type, u8 status,
7030 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007031{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007032 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007033
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007034 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007035 if (!cmd)
7036 return -ENOENT;
7037
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007038 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007039 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007040
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007041 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007042}
7043
Johan Hedberg744cf192011-11-08 20:40:14 +02007044int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007045 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007046{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007047 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007048 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007049}
7050
Johan Hedberg272d90d2012-02-09 15:26:12 +02007051int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007052 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007053{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007054 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007055 status,
7056 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007057}
Johan Hedberg2a611692011-02-19 12:06:00 -03007058
Brian Gix604086b2011-11-23 08:28:33 -08007059int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007060 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007061{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007062 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007063 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007064}
7065
Johan Hedberg272d90d2012-02-09 15:26:12 +02007066int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007067 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007068{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007069 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007070 status,
7071 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007072}
7073
Johan Hedberg92a25252012-09-06 18:39:26 +03007074int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7075 u8 link_type, u8 addr_type, u32 passkey,
7076 u8 entered)
7077{
7078 struct mgmt_ev_passkey_notify ev;
7079
7080 BT_DBG("%s", hdev->name);
7081
7082 bacpy(&ev.addr.bdaddr, bdaddr);
7083 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7084 ev.passkey = __cpu_to_le32(passkey);
7085 ev.entered = entered;
7086
7087 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7088}
7089
Johan Hedberge1e930f2014-09-08 17:09:49 -07007090void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007091{
7092 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007093 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007094 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007095
Johan Hedberge1e930f2014-09-08 17:09:49 -07007096 bacpy(&ev.addr.bdaddr, &conn->dst);
7097 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7098 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007099
Johan Hedberge1e930f2014-09-08 17:09:49 -07007100 cmd = find_pairing(conn);
7101
7102 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7103 cmd ? cmd->sk : NULL);
7104
Johan Hedberga511b352014-12-11 21:45:45 +02007105 if (cmd) {
7106 cmd->cmd_complete(cmd, status);
7107 mgmt_pending_remove(cmd);
7108 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007109}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007110
Marcel Holtmann464996a2013-10-15 14:26:24 -07007111void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007112{
7113 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007114 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007115
7116 if (status) {
7117 u8 mgmt_err = mgmt_status(status);
7118 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007119 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007120 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007121 }
7122
Marcel Holtmann464996a2013-10-15 14:26:24 -07007123 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007124 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007125 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007126 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007127
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007128 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007129 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007130
Johan Hedberg47990ea2012-02-22 11:58:37 +02007131 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007132 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007133
7134 if (match.sk)
7135 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007136}
7137
Johan Hedberg890ea892013-03-15 17:06:52 -05007138static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007139{
Johan Hedberg890ea892013-03-15 17:06:52 -05007140 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007141 struct hci_cp_write_eir cp;
7142
Johan Hedberg976eb202012-10-24 21:12:01 +03007143 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007144 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007145
Johan Hedbergc80da272012-02-22 15:38:48 +02007146 memset(hdev->eir, 0, sizeof(hdev->eir));
7147
Johan Hedbergcacaf522012-02-21 00:52:42 +02007148 memset(&cp, 0, sizeof(cp));
7149
Johan Hedberg890ea892013-03-15 17:06:52 -05007150 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007151}
7152
Marcel Holtmann3e248562013-10-15 14:26:25 -07007153void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007154{
7155 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007156 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007157 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007158
7159 if (status) {
7160 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007161
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007162 if (enable && hci_dev_test_and_clear_flag(hdev,
7163 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007164 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007165 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007166 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007167
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007168 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7169 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007170 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007171 }
7172
7173 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007174 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007175 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007176 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007177 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007178 changed = hci_dev_test_and_clear_flag(hdev,
7179 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007180 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007181 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007182 }
7183
7184 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7185
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007186 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007187 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007188
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007189 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007190 sock_put(match.sk);
7191
Johan Hedberg890ea892013-03-15 17:06:52 -05007192 hci_req_init(&req, hdev);
7193
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007194 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7195 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007196 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7197 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007198 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007199 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007200 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007201 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007202
7203 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007204}
7205
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007206static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007207{
7208 struct cmd_lookup *match = data;
7209
Johan Hedberg90e70452012-02-23 23:09:40 +02007210 if (match->sk == NULL) {
7211 match->sk = cmd->sk;
7212 sock_hold(match->sk);
7213 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007214}
7215
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007216void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7217 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007218{
Johan Hedberg90e70452012-02-23 23:09:40 +02007219 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007220
Johan Hedberg92da6092013-03-15 17:06:55 -05007221 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7222 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7223 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007224
7225 if (!status)
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007226 mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
7227 NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007228
7229 if (match.sk)
7230 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007231}
7232
Marcel Holtmann7667da32013-10-15 14:26:27 -07007233void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007234{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007235 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007236 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007237
Johan Hedberg13928972013-03-15 17:07:00 -05007238 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007239 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007240
7241 memset(&ev, 0, sizeof(ev));
7242 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007243 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007244
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007245 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007246 if (!cmd) {
7247 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007248
Johan Hedberg13928972013-03-15 17:07:00 -05007249 /* If this is a HCI command related to powering on the
7250 * HCI dev don't send any mgmt signals.
7251 */
7252 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007253 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007254 }
7255
Marcel Holtmann7667da32013-10-15 14:26:27 -07007256 mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7257 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007258}
Szymon Jancc35938b2011-03-22 13:12:21 +01007259
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007260void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007261 u8 *rand192, u8 *hash256, u8 *rand256,
7262 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007263{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007264 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007265
Johan Hedberg744cf192011-11-08 20:40:14 +02007266 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007267
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007268 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007269 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007270 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007271
7272 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007273 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7274 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007275 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007276 struct mgmt_rp_read_local_oob_data rp;
7277 size_t rp_size = sizeof(rp);
7278
7279 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7280 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7281
Johan Hedberg710f11c2014-05-26 11:21:22 +03007282 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007283 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007284 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007285 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007286 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007287 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007288
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007289 mgmt_cmd_complete(cmd->sk, hdev->id,
7290 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7291 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007292 }
7293
7294 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007295}
Johan Hedberge17acd42011-03-30 23:57:16 +03007296
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007297static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7298{
7299 int i;
7300
7301 for (i = 0; i < uuid_count; i++) {
7302 if (!memcmp(uuid, uuids[i], 16))
7303 return true;
7304 }
7305
7306 return false;
7307}
7308
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007309static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7310{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007311 u16 parsed = 0;
7312
7313 while (parsed < eir_len) {
7314 u8 field_len = eir[0];
7315 u8 uuid[16];
7316 int i;
7317
7318 if (field_len == 0)
7319 break;
7320
7321 if (eir_len - parsed < field_len + 1)
7322 break;
7323
7324 switch (eir[1]) {
7325 case EIR_UUID16_ALL:
7326 case EIR_UUID16_SOME:
7327 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007328 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007329 uuid[13] = eir[i + 3];
7330 uuid[12] = eir[i + 2];
7331 if (has_uuid(uuid, uuid_count, uuids))
7332 return true;
7333 }
7334 break;
7335 case EIR_UUID32_ALL:
7336 case EIR_UUID32_SOME:
7337 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007338 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007339 uuid[15] = eir[i + 5];
7340 uuid[14] = eir[i + 4];
7341 uuid[13] = eir[i + 3];
7342 uuid[12] = eir[i + 2];
7343 if (has_uuid(uuid, uuid_count, uuids))
7344 return true;
7345 }
7346 break;
7347 case EIR_UUID128_ALL:
7348 case EIR_UUID128_SOME:
7349 for (i = 0; i + 17 <= field_len; i += 16) {
7350 memcpy(uuid, eir + i + 2, 16);
7351 if (has_uuid(uuid, uuid_count, uuids))
7352 return true;
7353 }
7354 break;
7355 }
7356
7357 parsed += field_len + 1;
7358 eir += field_len + 1;
7359 }
7360
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007361 return false;
7362}
7363
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007364static void restart_le_scan(struct hci_dev *hdev)
7365{
7366 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007367 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007368 return;
7369
7370 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7371 hdev->discovery.scan_start +
7372 hdev->discovery.scan_duration))
7373 return;
7374
7375 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7376 DISCOV_LE_RESTART_DELAY);
7377}
7378
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007379static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7380 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7381{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007382 /* If a RSSI threshold has been specified, and
7383 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7384 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7385 * is set, let it through for further processing, as we might need to
7386 * restart the scan.
7387 *
7388 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7389 * the results are also dropped.
7390 */
7391 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7392 (rssi == HCI_RSSI_INVALID ||
7393 (rssi < hdev->discovery.rssi &&
7394 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7395 return false;
7396
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007397 if (hdev->discovery.uuid_count != 0) {
7398 /* If a list of UUIDs is provided in filter, results with no
7399 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007400 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007401 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7402 hdev->discovery.uuids) &&
7403 !eir_has_uuids(scan_rsp, scan_rsp_len,
7404 hdev->discovery.uuid_count,
7405 hdev->discovery.uuids))
7406 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007407 }
7408
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007409 /* If duplicate filtering does not report RSSI changes, then restart
7410 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007411 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007412 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7413 restart_le_scan(hdev);
7414
7415 /* Validate RSSI value against the RSSI threshold once more. */
7416 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7417 rssi < hdev->discovery.rssi)
7418 return false;
7419 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007420
7421 return true;
7422}
7423
Marcel Holtmann901801b2013-10-06 23:55:51 -07007424void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007425 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7426 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007427{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007428 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007429 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007430 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007431
Johan Hedberg75ce2082014-07-02 22:42:01 +03007432 /* Don't send events for a non-kernel initiated discovery. With
7433 * LE one exception is if we have pend_le_reports > 0 in which
7434 * case we're doing passive scanning and want these events.
7435 */
7436 if (!hci_discovery_active(hdev)) {
7437 if (link_type == ACL_LINK)
7438 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007439 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007440 return;
7441 }
Andre Guedes12602d02013-04-30 15:29:40 -03007442
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007443 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007444 /* We are using service discovery */
7445 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7446 scan_rsp_len))
7447 return;
7448 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007449
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007450 /* Make sure that the buffer is big enough. The 5 extra bytes
7451 * are for the potential CoD field.
7452 */
7453 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007454 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007455
Johan Hedberg1dc06092012-01-15 21:01:23 +02007456 memset(buf, 0, sizeof(buf));
7457
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007458 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7459 * RSSI value was reported as 0 when not available. This behavior
7460 * is kept when using device discovery. This is required for full
7461 * backwards compatibility with the API.
7462 *
7463 * However when using service discovery, the value 127 will be
7464 * returned when the RSSI is not available.
7465 */
Szymon Janc91200e92015-01-22 16:57:05 +01007466 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7467 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007468 rssi = 0;
7469
Johan Hedberg841c5642014-07-07 12:45:54 +03007470 bacpy(&ev->addr.bdaddr, bdaddr);
7471 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007472 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007473 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007474
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007475 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007476 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007477 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007478
Johan Hedberg1dc06092012-01-15 21:01:23 +02007479 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7480 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007481 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007482
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007483 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007484 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007485 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007486
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007487 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7488 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007489
Marcel Holtmann901801b2013-10-06 23:55:51 -07007490 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007491}
Johan Hedberga88a9652011-03-30 13:18:12 +03007492
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007493void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7494 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007495{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007496 struct mgmt_ev_device_found *ev;
7497 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7498 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007499
Johan Hedbergb644ba32012-01-17 21:48:47 +02007500 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007501
Johan Hedbergb644ba32012-01-17 21:48:47 +02007502 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007503
Johan Hedbergb644ba32012-01-17 21:48:47 +02007504 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007505 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007506 ev->rssi = rssi;
7507
7508 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007509 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007510
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007511 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007512
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007513 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007514}
Johan Hedberg314b2382011-04-27 10:29:57 -04007515
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007516void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007517{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007518 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007519
Andre Guedes343fb142011-11-22 17:14:19 -03007520 BT_DBG("%s discovering %u", hdev->name, discovering);
7521
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007522 memset(&ev, 0, sizeof(ev));
7523 ev.type = hdev->discovery.type;
7524 ev.discovering = discovering;
7525
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007526 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007527}
Antti Julku5e762442011-08-25 16:48:02 +03007528
Marcel Holtmann1904a852015-01-11 13:50:44 -08007529static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007530{
7531 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007532}
7533
7534void mgmt_reenable_advertising(struct hci_dev *hdev)
7535{
7536 struct hci_request req;
7537
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007538 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007539 return;
7540
7541 hci_req_init(&req, hdev);
7542 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007543 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007544}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007545
7546static struct hci_mgmt_chan chan = {
7547 .channel = HCI_CHANNEL_CONTROL,
7548 .handler_count = ARRAY_SIZE(mgmt_handlers),
7549 .handlers = mgmt_handlers,
7550};
7551
7552int mgmt_init(void)
7553{
7554 return hci_mgmt_chan_register(&chan);
7555}
7556
7557void mgmt_exit(void)
7558{
7559 hci_mgmt_chan_unregister(&chan);
7560}