blob: 5a4b9d5a224fb89e5fc531510982d3ca93b166f0 [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,
Marcel Holtmann4f0f1552015-03-14 22:43:19 -070099 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann96f14742015-03-14 19:27:57 -0700100 MGMT_OP_READ_EXT_INDEX_LIST,
Marcel Holtmannd3d53052015-03-14 20:53:25 -0700101 MGMT_OP_READ_ADV_FEATURES,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200102};
103
104static const u16 mgmt_events[] = {
105 MGMT_EV_CONTROLLER_ERROR,
106 MGMT_EV_INDEX_ADDED,
107 MGMT_EV_INDEX_REMOVED,
108 MGMT_EV_NEW_SETTINGS,
109 MGMT_EV_CLASS_OF_DEV_CHANGED,
110 MGMT_EV_LOCAL_NAME_CHANGED,
111 MGMT_EV_NEW_LINK_KEY,
112 MGMT_EV_NEW_LONG_TERM_KEY,
113 MGMT_EV_DEVICE_CONNECTED,
114 MGMT_EV_DEVICE_DISCONNECTED,
115 MGMT_EV_CONNECT_FAILED,
116 MGMT_EV_PIN_CODE_REQUEST,
117 MGMT_EV_USER_CONFIRM_REQUEST,
118 MGMT_EV_USER_PASSKEY_REQUEST,
119 MGMT_EV_AUTH_FAILED,
120 MGMT_EV_DEVICE_FOUND,
121 MGMT_EV_DISCOVERING,
122 MGMT_EV_DEVICE_BLOCKED,
123 MGMT_EV_DEVICE_UNBLOCKED,
124 MGMT_EV_DEVICE_UNPAIRED,
Johan Hedberg92a25252012-09-06 18:39:26 +0300125 MGMT_EV_PASSKEY_NOTIFY,
Marcel Holtmann1b60ef22014-02-21 21:35:30 -0800126 MGMT_EV_NEW_IRK,
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -0700127 MGMT_EV_NEW_CSRK,
Marcel Holtmann8afef092014-06-29 22:28:34 +0200128 MGMT_EV_DEVICE_ADDED,
129 MGMT_EV_DEVICE_REMOVED,
Andre Guedesffb5a8272014-07-01 18:10:11 -0300130 MGMT_EV_NEW_CONN_PARAM,
Marcel Holtmann0602a8a2014-07-02 21:30:54 +0200131 MGMT_EV_UNCONF_INDEX_ADDED,
Marcel Holtmannedd38962014-07-02 21:30:55 +0200132 MGMT_EV_UNCONF_INDEX_REMOVED,
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200133 MGMT_EV_NEW_CONFIG_OPTIONS,
Marcel Holtmannced85542015-03-14 19:27:56 -0700134 MGMT_EV_EXT_INDEX_ADDED,
135 MGMT_EV_EXT_INDEX_REMOVED,
Marcel Holtmann72000df2015-03-16 16:11:21 -0700136 MGMT_EV_LOCAL_OOB_DATA_UPDATED,
Johan Hedberge70bb2e2012-02-13 16:59:33 +0200137};
138
Marcel Holtmann17b02e62012-03-01 14:32:37 -0800139#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
Johan Hedberg7d785252011-12-15 00:47:39 +0200140
Johan Hedbergd25b78e2015-01-27 12:55:52 +0200141#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
142 "\x00\x00\x00\x00\x00\x00\x00\x00"
143
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200144struct mgmt_pending_cmd {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200145 struct list_head list;
Johan Hedbergfc2f4b12011-11-09 13:58:56 +0200146 u16 opcode;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200147 int index;
Szymon Jancc68fb7f2011-03-22 13:12:19 +0100148 void *param;
Johan Hedberg323b0b82014-12-05 13:36:01 +0200149 size_t param_len;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200150 struct sock *sk;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300151 void *user_data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200152 int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200153};
154
Johan Hedbergca69b792011-11-11 18:10:00 +0200155/* HCI to MGMT error code conversion table */
156static u8 mgmt_status_table[] = {
157 MGMT_STATUS_SUCCESS,
158 MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
159 MGMT_STATUS_NOT_CONNECTED, /* No Connection */
160 MGMT_STATUS_FAILED, /* Hardware Failure */
161 MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
162 MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
Johan Hedbergeadd6632014-01-13 17:15:53 +0200163 MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
Johan Hedbergca69b792011-11-11 18:10:00 +0200164 MGMT_STATUS_NO_RESOURCES, /* Memory Full */
165 MGMT_STATUS_TIMEOUT, /* Connection Timeout */
166 MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
167 MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
168 MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
169 MGMT_STATUS_BUSY, /* Command Disallowed */
170 MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
171 MGMT_STATUS_REJECTED, /* Rejected Security */
172 MGMT_STATUS_REJECTED, /* Rejected Personal */
173 MGMT_STATUS_TIMEOUT, /* Host Timeout */
174 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
175 MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
176 MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
177 MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
178 MGMT_STATUS_DISCONNECTED, /* OE Power Off */
179 MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
180 MGMT_STATUS_BUSY, /* Repeated Attempts */
181 MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
182 MGMT_STATUS_FAILED, /* Unknown LMP PDU */
183 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
184 MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
185 MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
186 MGMT_STATUS_REJECTED, /* Air Mode Rejected */
187 MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
188 MGMT_STATUS_FAILED, /* Unspecified Error */
189 MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
190 MGMT_STATUS_FAILED, /* Role Change Not Allowed */
191 MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
192 MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
193 MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
194 MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
195 MGMT_STATUS_FAILED, /* Unit Link Key Used */
196 MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
197 MGMT_STATUS_TIMEOUT, /* Instant Passed */
198 MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
199 MGMT_STATUS_FAILED, /* Transaction Collision */
200 MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
201 MGMT_STATUS_REJECTED, /* QoS Rejected */
202 MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
203 MGMT_STATUS_REJECTED, /* Insufficient Security */
204 MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
205 MGMT_STATUS_BUSY, /* Role Switch Pending */
206 MGMT_STATUS_FAILED, /* Slot Violation */
207 MGMT_STATUS_FAILED, /* Role Switch Failed */
208 MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
209 MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
210 MGMT_STATUS_BUSY, /* Host Busy Pairing */
211 MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
212 MGMT_STATUS_BUSY, /* Controller Busy */
213 MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
214 MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
215 MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
216 MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
217 MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
218};
219
220static u8 mgmt_status(u8 hci_status)
221{
222 if (hci_status < ARRAY_SIZE(mgmt_status_table))
223 return mgmt_status_table[hci_status];
224
225 return MGMT_STATUS_FAILED;
226}
227
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200228static int mgmt_send_event(u16 event, struct hci_dev *hdev,
229 unsigned short channel, void *data, u16 data_len,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700230 int flag, struct sock *skip_sk)
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200231{
232 struct sk_buff *skb;
233 struct mgmt_hdr *hdr;
234
235 skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL);
236 if (!skb)
237 return -ENOMEM;
238
239 hdr = (void *) skb_put(skb, sizeof(*hdr));
240 hdr->opcode = cpu_to_le16(event);
241 if (hdev)
242 hdr->index = cpu_to_le16(hdev->id);
243 else
244 hdr->index = cpu_to_le16(MGMT_INDEX_NONE);
245 hdr->len = cpu_to_le16(data_len);
246
247 if (data)
248 memcpy(skb_put(skb, data_len), data, data_len);
249
250 /* Time stamp */
251 __net_timestamp(skb);
252
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700253 hci_send_to_channel(channel, skb, flag, skip_sk);
Marcel Holtmann04c60f052014-07-04 19:06:22 +0200254 kfree_skb(skb);
255
256 return 0;
257}
258
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700259static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
260 u16 len, int flag)
Marcel Holtmannf9207332015-03-14 19:27:55 -0700261{
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700262 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
263 flag, NULL);
Marcel Holtmannf9207332015-03-14 19:27:55 -0700264}
265
Marcel Holtmann72000df2015-03-16 16:11:21 -0700266static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
267 u16 len, int flag, struct sock *skip_sk)
268{
269 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
270 flag, skip_sk);
271}
272
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700273static int mgmt_generic_event(u16 event, struct hci_dev *hdev, void *data,
274 u16 len, struct sock *skip_sk)
275{
276 return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
277 HCI_MGMT_GENERIC_EVENTS, skip_sk);
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,
Marcel Holtmannc08b1a12015-03-14 19:27:59 -0700284 HCI_SOCK_TRUSTED, skip_sk);
Johan Hedberg7a00ff42015-03-06 21:08:56 +0200285}
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 Holtmann96f14742015-03-14 19:27:57 -0700519static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
520 void *data, u16 data_len)
521{
522 struct mgmt_rp_read_ext_index_list *rp;
523 struct hci_dev *d;
524 size_t rp_len;
525 u16 count;
526 int err;
527
528 BT_DBG("sock %p", sk);
529
530 read_lock(&hci_dev_list_lock);
531
532 count = 0;
533 list_for_each_entry(d, &hci_dev_list, list) {
534 if (d->dev_type == HCI_BREDR || d->dev_type == HCI_AMP)
535 count++;
536 }
537
538 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
539 rp = kmalloc(rp_len, GFP_ATOMIC);
540 if (!rp) {
541 read_unlock(&hci_dev_list_lock);
542 return -ENOMEM;
543 }
544
545 count = 0;
546 list_for_each_entry(d, &hci_dev_list, list) {
547 if (hci_dev_test_flag(d, HCI_SETUP) ||
548 hci_dev_test_flag(d, HCI_CONFIG) ||
549 hci_dev_test_flag(d, HCI_USER_CHANNEL))
550 continue;
551
552 /* Devices marked as raw-only are neither configured
553 * nor unconfigured controllers.
554 */
555 if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
556 continue;
557
558 if (d->dev_type == HCI_BREDR) {
559 if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
560 rp->entry[count].type = 0x01;
561 else
562 rp->entry[count].type = 0x00;
563 } else if (d->dev_type == HCI_AMP) {
564 rp->entry[count].type = 0x02;
565 } else {
566 continue;
567 }
568
569 rp->entry[count].bus = d->bus;
570 rp->entry[count++].index = cpu_to_le16(d->id);
571 BT_DBG("Added hci%u", d->id);
572 }
573
574 rp->num_controllers = cpu_to_le16(count);
575 rp_len = sizeof(*rp) + (sizeof(rp->entry[0]) * count);
576
577 read_unlock(&hci_dev_list_lock);
578
579 /* If this command is called at least once, then all the
580 * default index and unconfigured index events are disabled
581 * and from now on only extended index events are used.
582 */
583 hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
584 hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
585 hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
586
587 err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
588 MGMT_OP_READ_EXT_INDEX_LIST, 0, rp, rp_len);
589
590 kfree(rp);
591
592 return err;
593}
594
Marcel Holtmanndbece372014-07-04 18:11:55 +0200595static bool is_configured(struct hci_dev *hdev)
596{
597 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700598 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanndbece372014-07-04 18:11:55 +0200599 return false;
600
601 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
602 !bacmp(&hdev->public_addr, BDADDR_ANY))
603 return false;
604
605 return true;
606}
607
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200608static __le32 get_missing_options(struct hci_dev *hdev)
609{
610 u32 options = 0;
611
Marcel Holtmanndbece372014-07-04 18:11:55 +0200612 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700613 !hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200614 options |= MGMT_OPTION_EXTERNAL_CONFIG;
615
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200616 if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) &&
617 !bacmp(&hdev->public_addr, BDADDR_ANY))
618 options |= MGMT_OPTION_PUBLIC_ADDRESS;
619
620 return cpu_to_le32(options);
621}
622
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200623static int new_options(struct hci_dev *hdev, struct sock *skip)
624{
625 __le32 options = get_missing_options(hdev);
626
Marcel Holtmannf6b77122015-03-14 19:28:05 -0700627 return mgmt_generic_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
628 sizeof(options), skip);
Marcel Holtmannf4537c02014-07-04 19:06:23 +0200629}
630
Marcel Holtmanndbece372014-07-04 18:11:55 +0200631static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
632{
633 __le32 options = get_missing_options(hdev);
634
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200635 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
636 sizeof(options));
Marcel Holtmanndbece372014-07-04 18:11:55 +0200637}
638
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200639static int read_config_info(struct sock *sk, struct hci_dev *hdev,
640 void *data, u16 data_len)
641{
642 struct mgmt_rp_read_config_info rp;
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200643 u32 options = 0;
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200644
645 BT_DBG("sock %p %s", sk, hdev->name);
646
647 hci_dev_lock(hdev);
648
649 memset(&rp, 0, sizeof(rp));
650 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200651
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200652 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
653 options |= MGMT_OPTION_EXTERNAL_CONFIG;
654
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200655 if (hdev->set_bdaddr)
Marcel Holtmann89bc22d2014-07-04 16:54:37 +0200656 options |= MGMT_OPTION_PUBLIC_ADDRESS;
657
658 rp.supported_options = cpu_to_le32(options);
659 rp.missing_options = get_missing_options(hdev);
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200660
661 hci_dev_unlock(hdev);
662
Johan Hedberg2a1afb52015-03-06 21:08:54 +0200663 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
664 &rp, sizeof(rp));
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200665}
666
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200667static u32 get_supported_settings(struct hci_dev *hdev)
Johan Hedberg03811012010-12-08 00:21:06 +0200668{
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200669 u32 settings = 0;
Johan Hedberg03811012010-12-08 00:21:06 +0200670
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200671 settings |= MGMT_SETTING_POWERED;
Johan Hedbergb2939472014-07-30 09:22:23 +0300672 settings |= MGMT_SETTING_BONDABLE;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800673 settings |= MGMT_SETTING_DEBUG_KEYS;
Johan Hedberg3742abf2014-07-08 16:07:34 +0300674 settings |= MGMT_SETTING_CONNECTABLE;
675 settings |= MGMT_SETTING_DISCOVERABLE;
Johan Hedberg03811012010-12-08 00:21:06 +0200676
Andre Guedesed3fa312012-07-24 15:03:46 -0300677 if (lmp_bredr_capable(hdev)) {
Johan Hedberg1a47aee2013-03-15 17:07:06 -0500678 if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
679 settings |= MGMT_SETTING_FAST_CONNECTABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200680 settings |= MGMT_SETTING_BREDR;
681 settings |= MGMT_SETTING_LINK_SECURITY;
Marcel Holtmanna82974c2013-10-11 09:48:47 -0700682
683 if (lmp_ssp_capable(hdev)) {
684 settings |= MGMT_SETTING_SSP;
685 settings |= MGMT_SETTING_HS;
686 }
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800687
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -0800688 if (lmp_sc_capable(hdev))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800689 settings |= MGMT_SETTING_SECURE_CONN;
Marcel Holtmann848566b2013-10-01 22:59:22 -0700690 }
Marcel Holtmannd7b7e792012-02-20 21:47:49 +0100691
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300692 if (lmp_le_capable(hdev)) {
Marcel Holtmann9d428202012-05-03 07:12:31 +0200693 settings |= MGMT_SETTING_LE;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300694 settings |= MGMT_SETTING_ADVERTISING;
Johan Hedberga3209692014-05-26 11:23:35 +0300695 settings |= MGMT_SETTING_SECURE_CONN;
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200696 settings |= MGMT_SETTING_PRIVACY;
Marcel Holtmann93690c22015-03-06 10:11:21 -0800697 settings |= MGMT_SETTING_STATIC_ADDRESS;
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300698 }
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200699
Marcel Holtmanneb1904f2014-07-04 17:23:33 +0200700 if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
701 hdev->set_bdaddr)
Marcel Holtmann9fc3bfb2014-07-04 00:46:56 +0200702 settings |= MGMT_SETTING_CONFIGURATION;
703
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200704 return settings;
705}
Johan Hedbergebc99fe2011-01-04 11:54:26 +0200706
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200707static u32 get_current_settings(struct hci_dev *hdev)
708{
709 u32 settings = 0;
Johan Hedbergdc4fe302011-03-16 14:29:36 +0200710
Johan Hedbergf1f0eb02012-02-21 17:15:41 +0200711 if (hdev_is_powered(hdev))
Marcel Holtmannf0d4b782012-02-21 12:14:25 +0100712 settings |= MGMT_SETTING_POWERED;
713
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700714 if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200715 settings |= MGMT_SETTING_CONNECTABLE;
716
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700717 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg1a4d3c42013-03-15 17:07:08 -0500718 settings |= MGMT_SETTING_FAST_CONNECTABLE;
719
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700720 if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200721 settings |= MGMT_SETTING_DISCOVERABLE;
722
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700723 if (hci_dev_test_flag(hdev, HCI_BONDABLE))
Johan Hedbergb2939472014-07-30 09:22:23 +0300724 settings |= MGMT_SETTING_BONDABLE;
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200725
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700726 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200727 settings |= MGMT_SETTING_BREDR;
728
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700729 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200730 settings |= MGMT_SETTING_LE;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200731
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700732 if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200733 settings |= MGMT_SETTING_LINK_SECURITY;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200734
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700735 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200736 settings |= MGMT_SETTING_SSP;
Johan Hedbergf7b64e692010-12-13 21:07:06 +0200737
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700738 if (hci_dev_test_flag(hdev, HCI_HS_ENABLED))
Johan Hedberg6d80dfd2012-02-20 23:50:38 +0200739 settings |= MGMT_SETTING_HS;
740
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700741 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergeeca6f82013-09-25 13:26:09 +0300742 settings |= MGMT_SETTING_ADVERTISING;
743
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700744 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
Marcel Holtmanne98d2ce2014-01-10 02:07:22 -0800745 settings |= MGMT_SETTING_SECURE_CONN;
746
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700747 if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
Marcel Holtmannb1de97d2014-01-31 11:55:21 -0800748 settings |= MGMT_SETTING_DEBUG_KEYS;
749
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700750 if (hci_dev_test_flag(hdev, HCI_PRIVACY))
Johan Hedberg0f4bd942014-02-22 19:06:35 +0200751 settings |= MGMT_SETTING_PRIVACY;
752
Marcel Holtmann93690c22015-03-06 10:11:21 -0800753 /* The current setting for static address has two purposes. The
754 * first is to indicate if the static address will be used and
755 * the second is to indicate if it is actually set.
756 *
757 * This means if the static address is not configured, this flag
758 * will never bet set. If the address is configured, then if the
759 * address is actually used decides if the flag is set or not.
760 *
761 * For single mode LE only controllers and dual-mode controllers
762 * with BR/EDR disabled, the existence of the static address will
763 * be evaluated.
764 */
Marcel Holtmannb7cb93e2015-03-13 10:20:35 -0700765 if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700766 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Marcel Holtmann93690c22015-03-06 10:11:21 -0800767 !bacmp(&hdev->bdaddr, BDADDR_ANY)) {
768 if (bacmp(&hdev->static_addr, BDADDR_ANY))
769 settings |= MGMT_SETTING_STATIC_ADDRESS;
770 }
771
Johan Hedberg69ab39e2011-12-15 00:47:35 +0200772 return settings;
Johan Hedbergc542a062011-01-26 13:11:03 +0200773}
774
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300775#define PNP_INFO_SVCLASS_ID 0x1200
776
Johan Hedberg213202e2013-01-27 00:31:33 +0200777static u8 *create_uuid16_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
778{
779 u8 *ptr = data, *uuids_start = NULL;
780 struct bt_uuid *uuid;
781
782 if (len < 4)
783 return ptr;
784
785 list_for_each_entry(uuid, &hdev->uuids, list) {
786 u16 uuid16;
787
788 if (uuid->size != 16)
789 continue;
790
791 uuid16 = get_unaligned_le16(&uuid->uuid[12]);
792 if (uuid16 < 0x1100)
793 continue;
794
795 if (uuid16 == PNP_INFO_SVCLASS_ID)
796 continue;
797
798 if (!uuids_start) {
799 uuids_start = ptr;
800 uuids_start[0] = 1;
801 uuids_start[1] = EIR_UUID16_ALL;
802 ptr += 2;
803 }
804
805 /* Stop if not enough space to put next UUID */
806 if ((ptr - data) + sizeof(u16) > len) {
807 uuids_start[1] = EIR_UUID16_SOME;
808 break;
809 }
810
811 *ptr++ = (uuid16 & 0x00ff);
812 *ptr++ = (uuid16 & 0xff00) >> 8;
813 uuids_start[0] += sizeof(uuid16);
814 }
815
816 return ptr;
817}
818
Johan Hedbergcdf19632013-01-27 00:31:34 +0200819static u8 *create_uuid32_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
820{
821 u8 *ptr = data, *uuids_start = NULL;
822 struct bt_uuid *uuid;
823
824 if (len < 6)
825 return ptr;
826
827 list_for_each_entry(uuid, &hdev->uuids, list) {
828 if (uuid->size != 32)
829 continue;
830
831 if (!uuids_start) {
832 uuids_start = ptr;
833 uuids_start[0] = 1;
834 uuids_start[1] = EIR_UUID32_ALL;
835 ptr += 2;
836 }
837
838 /* Stop if not enough space to put next UUID */
839 if ((ptr - data) + sizeof(u32) > len) {
840 uuids_start[1] = EIR_UUID32_SOME;
841 break;
842 }
843
844 memcpy(ptr, &uuid->uuid[12], sizeof(u32));
845 ptr += sizeof(u32);
846 uuids_start[0] += sizeof(u32);
847 }
848
849 return ptr;
850}
851
Johan Hedbergc00d5752013-01-27 00:31:35 +0200852static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
853{
854 u8 *ptr = data, *uuids_start = NULL;
855 struct bt_uuid *uuid;
856
857 if (len < 18)
858 return ptr;
859
860 list_for_each_entry(uuid, &hdev->uuids, list) {
861 if (uuid->size != 128)
862 continue;
863
864 if (!uuids_start) {
865 uuids_start = ptr;
866 uuids_start[0] = 1;
867 uuids_start[1] = EIR_UUID128_ALL;
868 ptr += 2;
869 }
870
871 /* Stop if not enough space to put next UUID */
872 if ((ptr - data) + 16 > len) {
873 uuids_start[1] = EIR_UUID128_SOME;
874 break;
875 }
876
877 memcpy(ptr, uuid->uuid, 16);
878 ptr += 16;
879 uuids_start[0] += 16;
880 }
881
882 return ptr;
883}
884
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200885static struct mgmt_pending_cmd *mgmt_pending_find(u16 opcode,
886 struct hci_dev *hdev)
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300887{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200888 struct mgmt_pending_cmd *cmd;
Johan Hedbergeb2a8d22013-10-19 23:38:20 +0300889
890 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
891 if (cmd->opcode == opcode)
892 return cmd;
893 }
894
895 return NULL;
896}
897
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200898static struct mgmt_pending_cmd *mgmt_pending_find_data(u16 opcode,
899 struct hci_dev *hdev,
900 const void *data)
Johan Hedberg95868422014-06-28 17:54:07 +0300901{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200902 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +0300903
904 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
905 if (cmd->user_data != data)
906 continue;
907 if (cmd->opcode == opcode)
908 return cmd;
909 }
910
911 return NULL;
912}
913
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700914static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
915{
Marcel Holtmann7a5f4992013-10-16 00:16:49 -0700916 u8 ad_len = 0;
917 size_t name_len;
918
919 name_len = strlen(hdev->dev_name);
920 if (name_len > 0) {
921 size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
922
923 if (name_len > max_len) {
924 name_len = max_len;
925 ptr[1] = EIR_NAME_SHORT;
926 } else
927 ptr[1] = EIR_NAME_COMPLETE;
928
929 ptr[0] = name_len + 1;
930
931 memcpy(ptr + 2, hdev->dev_name, name_len);
932
933 ad_len += (name_len + 2);
934 ptr += (name_len + 2);
935 }
936
937 return ad_len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700938}
939
940static void update_scan_rsp_data(struct hci_request *req)
941{
942 struct hci_dev *hdev = req->hdev;
943 struct hci_cp_le_set_scan_rsp_data cp;
944 u8 len;
945
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700946 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700947 return;
948
949 memset(&cp, 0, sizeof(cp));
950
951 len = create_scan_rsp_data(hdev, cp.data);
952
Johan Hedbergeb438b52013-10-16 15:31:07 +0300953 if (hdev->scan_rsp_data_len == len &&
954 memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700955 return;
956
Johan Hedbergeb438b52013-10-16 15:31:07 +0300957 memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
958 hdev->scan_rsp_data_len = len;
Marcel Holtmannf14d8f62013-10-16 00:16:48 -0700959
960 cp.length = len;
961
962 hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
963}
964
Johan Hedberg9a43e252013-10-20 19:00:07 +0300965static u8 get_adv_discov_flags(struct hci_dev *hdev)
966{
Johan Hedberg3b0602c2015-03-06 21:08:55 +0200967 struct mgmt_pending_cmd *cmd;
Johan Hedberg9a43e252013-10-20 19:00:07 +0300968
969 /* If there's a pending mgmt command the flags will not yet have
970 * their final values, so check for this first.
971 */
972 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
973 if (cmd) {
974 struct mgmt_mode *cp = cmd->param;
975 if (cp->val == 0x01)
976 return LE_AD_GENERAL;
977 else if (cp->val == 0x02)
978 return LE_AD_LIMITED;
979 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700980 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300981 return LE_AD_LIMITED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700982 else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
Johan Hedberg9a43e252013-10-20 19:00:07 +0300983 return LE_AD_GENERAL;
984 }
985
986 return 0;
987}
988
Marcel Holtmann46cad2e2013-10-16 00:16:46 -0700989static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700990{
991 u8 ad_len = 0, flags = 0;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700992
Johan Hedberg9a43e252013-10-20 19:00:07 +0300993 flags |= get_adv_discov_flags(hdev);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700994
Marcel Holtmannd7a5a112015-03-13 02:11:00 -0700995 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700996 flags |= LE_AD_NO_BREDR;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -0700997
998 if (flags) {
999 BT_DBG("adv flags 0x%02x", flags);
1000
1001 ptr[0] = 2;
1002 ptr[1] = EIR_FLAGS;
1003 ptr[2] = flags;
1004
1005 ad_len += 3;
1006 ptr += 3;
1007 }
1008
1009 if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
1010 ptr[0] = 2;
1011 ptr[1] = EIR_TX_POWER;
1012 ptr[2] = (u8) hdev->adv_tx_power;
1013
1014 ad_len += 3;
1015 ptr += 3;
1016 }
1017
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001018 return ad_len;
1019}
1020
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07001021static void update_adv_data(struct hci_request *req)
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001022{
1023 struct hci_dev *hdev = req->hdev;
1024 struct hci_cp_le_set_adv_data cp;
1025 u8 len;
1026
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001027 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001028 return;
1029
1030 memset(&cp, 0, sizeof(cp));
1031
Marcel Holtmann46cad2e2013-10-16 00:16:46 -07001032 len = create_adv_data(hdev, cp.data);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07001033
1034 if (hdev->adv_data_len == len &&
1035 memcmp(cp.data, hdev->adv_data, len) == 0)
1036 return;
1037
1038 memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
1039 hdev->adv_data_len = len;
1040
1041 cp.length = len;
1042
1043 hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
1044}
1045
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001046int mgmt_update_adv_data(struct hci_dev *hdev)
1047{
1048 struct hci_request req;
1049
1050 hci_req_init(&req, hdev);
1051 update_adv_data(&req);
1052
1053 return hci_req_run(&req, NULL);
1054}
1055
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001056static void create_eir(struct hci_dev *hdev, u8 *data)
1057{
1058 u8 *ptr = data;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001059 size_t name_len;
1060
1061 name_len = strlen(hdev->dev_name);
1062
1063 if (name_len > 0) {
1064 /* EIR Data type */
1065 if (name_len > 48) {
1066 name_len = 48;
1067 ptr[1] = EIR_NAME_SHORT;
1068 } else
1069 ptr[1] = EIR_NAME_COMPLETE;
1070
1071 /* EIR Data length */
1072 ptr[0] = name_len + 1;
1073
1074 memcpy(ptr + 2, hdev->dev_name, name_len);
1075
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001076 ptr += (name_len + 2);
1077 }
1078
Johan Hedbergbbaf4442012-11-08 01:22:59 +01001079 if (hdev->inq_tx_power != HCI_TX_POWER_INVALID) {
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001080 ptr[0] = 2;
1081 ptr[1] = EIR_TX_POWER;
1082 ptr[2] = (u8) hdev->inq_tx_power;
1083
Marcel Holtmann91c4e9b2012-03-11 19:27:21 -07001084 ptr += 3;
1085 }
1086
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001087 if (hdev->devid_source > 0) {
1088 ptr[0] = 9;
1089 ptr[1] = EIR_DEVICE_ID;
1090
1091 put_unaligned_le16(hdev->devid_source, ptr + 2);
1092 put_unaligned_le16(hdev->devid_vendor, ptr + 4);
1093 put_unaligned_le16(hdev->devid_product, ptr + 6);
1094 put_unaligned_le16(hdev->devid_version, ptr + 8);
1095
Marcel Holtmann2b9be132012-03-11 19:32:12 -07001096 ptr += 10;
1097 }
1098
Johan Hedberg213202e2013-01-27 00:31:33 +02001099 ptr = create_uuid16_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergcdf19632013-01-27 00:31:34 +02001100 ptr = create_uuid32_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedbergc00d5752013-01-27 00:31:35 +02001101 ptr = create_uuid128_list(hdev, ptr, HCI_MAX_EIR_LENGTH - (ptr - data));
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001102}
1103
Johan Hedberg890ea892013-03-15 17:06:52 -05001104static void update_eir(struct hci_request *req)
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001105{
Johan Hedberg890ea892013-03-15 17:06:52 -05001106 struct hci_dev *hdev = req->hdev;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001107 struct hci_cp_write_eir cp;
1108
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001109 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001110 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001111
Johan Hedberg976eb202012-10-24 21:12:01 +03001112 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001113 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001114
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001115 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberg890ea892013-03-15 17:06:52 -05001116 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001117
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001118 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001119 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001120
1121 memset(&cp, 0, sizeof(cp));
1122
1123 create_eir(hdev, cp.data);
1124
1125 if (memcmp(cp.data, hdev->eir, sizeof(cp.data)) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001126 return;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001127
1128 memcpy(hdev->eir, cp.data, sizeof(cp.data));
1129
Johan Hedberg890ea892013-03-15 17:06:52 -05001130 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03001131}
1132
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001133static u8 get_service_classes(struct hci_dev *hdev)
1134{
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001135 struct bt_uuid *uuid;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001136 u8 val = 0;
1137
Gustavo F. Padovan12dc0742011-10-14 19:32:56 -03001138 list_for_each_entry(uuid, &hdev->uuids, list)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001139 val |= uuid->svc_hint;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001140
1141 return val;
1142}
1143
Johan Hedberg890ea892013-03-15 17:06:52 -05001144static void update_class(struct hci_request *req)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001145{
Johan Hedberg890ea892013-03-15 17:06:52 -05001146 struct hci_dev *hdev = req->hdev;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001147 u8 cod[3];
1148
1149 BT_DBG("%s", hdev->name);
1150
Johan Hedberg504c8dc2012-02-23 13:30:41 +02001151 if (!hdev_is_powered(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05001152 return;
Johan Hedberg7770c4a2012-02-22 22:06:38 +02001153
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001154 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedbergf87ea1d2013-10-19 23:38:17 +03001155 return;
1156
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001157 if (hci_dev_test_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg890ea892013-03-15 17:06:52 -05001158 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001159
1160 cod[0] = hdev->minor_class;
1161 cod[1] = hdev->major_class;
1162 cod[2] = get_service_classes(hdev);
1163
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001164 if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
Marcel Holtmann6acd7db2013-10-15 06:33:53 -07001165 cod[1] |= 0x20;
1166
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001167 if (memcmp(cod, hdev->dev_class, 3) == 0)
Johan Hedberg890ea892013-03-15 17:06:52 -05001168 return;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001169
Johan Hedberg890ea892013-03-15 17:06:52 -05001170 hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02001171}
1172
Johan Hedberga4858cb2014-02-25 19:56:31 +02001173static bool get_connectable(struct hci_dev *hdev)
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001174{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001175 struct mgmt_pending_cmd *cmd;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001176
1177 /* If there's a pending mgmt command the flag will not yet have
1178 * it's final value, so check for this first.
1179 */
1180 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1181 if (cmd) {
1182 struct mgmt_mode *cp = cmd->param;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001183 return cp->val;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001184 }
1185
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001186 return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001187}
1188
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001189static void disable_advertising(struct hci_request *req)
1190{
1191 u8 enable = 0x00;
1192
1193 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1194}
1195
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001196static void enable_advertising(struct hci_request *req)
1197{
1198 struct hci_dev *hdev = req->hdev;
1199 struct hci_cp_le_set_adv_param cp;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001200 u8 own_addr_type, enable = 0x01;
Johan Hedberga4858cb2014-02-25 19:56:31 +02001201 bool connectable;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001202
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001203 if (hci_conn_num(hdev, LE_LINK) > 0)
1204 return;
1205
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001206 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03001207 disable_advertising(req);
1208
Johan Hedberg5ce194c2014-07-08 15:07:49 +03001209 /* Clear the HCI_LE_ADV bit temporarily so that the
Johan Hedberg8d972502014-02-28 12:54:14 +02001210 * hci_update_random_address knows that it's safe to go ahead
1211 * and write a new random address. The flag will be set back on
1212 * as soon as the SET_ADV_ENABLE HCI command completes.
1213 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001214 hci_dev_clear_flag(hdev, HCI_LE_ADV);
Johan Hedberg8d972502014-02-28 12:54:14 +02001215
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001216 if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE))
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07001217 connectable = true;
1218 else
1219 connectable = get_connectable(hdev);
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001220
Johan Hedberga4858cb2014-02-25 19:56:31 +02001221 /* Set require_privacy to true only when non-connectable
1222 * advertising is used. In that case it is fine to use a
1223 * non-resolvable private address.
1224 */
1225 if (hci_update_random_address(req, !connectable, &own_addr_type) < 0)
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001226 return;
1227
Marcel Holtmann41c90c12014-02-23 20:25:55 -08001228 memset(&cp, 0, sizeof(cp));
Georg Lukas628531c2014-07-26 13:59:57 +02001229 cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval);
1230 cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval);
Johan Hedberga4858cb2014-02-25 19:56:31 +02001231 cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND;
Johan Hedberg8f2a0602014-02-23 19:42:23 +02001232 cp.own_address_type = own_addr_type;
Johan Hedberg199a2fb2014-02-22 19:06:33 +02001233 cp.channel_map = hdev->le_adv_channel_map;
1234
1235 hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
1236
1237 hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable);
1238}
1239
Johan Hedberg7d785252011-12-15 00:47:39 +02001240static void service_cache_off(struct work_struct *work)
1241{
1242 struct hci_dev *hdev = container_of(work, struct hci_dev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001243 service_cache.work);
Johan Hedberg890ea892013-03-15 17:06:52 -05001244 struct hci_request req;
Johan Hedberg7d785252011-12-15 00:47:39 +02001245
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001246 if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
Johan Hedberg7d785252011-12-15 00:47:39 +02001247 return;
1248
Johan Hedberg890ea892013-03-15 17:06:52 -05001249 hci_req_init(&req, hdev);
1250
Johan Hedberg7d785252011-12-15 00:47:39 +02001251 hci_dev_lock(hdev);
1252
Johan Hedberg890ea892013-03-15 17:06:52 -05001253 update_eir(&req);
1254 update_class(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02001255
1256 hci_dev_unlock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05001257
1258 hci_req_run(&req, NULL);
Johan Hedberg7d785252011-12-15 00:47:39 +02001259}
1260
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001261static void rpa_expired(struct work_struct *work)
1262{
1263 struct hci_dev *hdev = container_of(work, struct hci_dev,
1264 rpa_expired.work);
1265 struct hci_request req;
1266
1267 BT_DBG("");
1268
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001269 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001270
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001271 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001272 return;
1273
1274 /* The generation of a new RPA and programming it into the
1275 * controller happens in the enable_advertising() function.
1276 */
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001277 hci_req_init(&req, hdev);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001278 enable_advertising(&req);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001279 hci_req_run(&req, NULL);
1280}
1281
Johan Hedberg6a919082012-02-28 06:17:26 +02001282static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
Johan Hedberg7d785252011-12-15 00:47:39 +02001283{
Marcel Holtmann238be782015-03-13 02:11:06 -07001284 if (hci_dev_test_and_set_flag(hdev, HCI_MGMT))
Johan Hedberg6a919082012-02-28 06:17:26 +02001285 return;
1286
Johan Hedberg4f87da82012-03-02 19:55:56 +02001287 INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
Johan Hedbergd6bfd592014-02-23 19:42:20 +02001288 INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
Johan Hedberg7d785252011-12-15 00:47:39 +02001289
Johan Hedberg4f87da82012-03-02 19:55:56 +02001290 /* Non-mgmt controlled devices get this bit set
1291 * implicitly so that pairing works for them, however
1292 * for mgmt we require user-space to explicitly enable
1293 * it
1294 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001295 hci_dev_clear_flag(hdev, HCI_BONDABLE);
Johan Hedberg7d785252011-12-15 00:47:39 +02001296}
1297
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02001298static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001299 void *data, u16 data_len)
Johan Hedberg03811012010-12-08 00:21:06 +02001300{
1301 struct mgmt_rp_read_info rp;
Johan Hedberg03811012010-12-08 00:21:06 +02001302
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001303 BT_DBG("sock %p %s", sk, hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001304
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001305 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001306
Johan Hedberg03811012010-12-08 00:21:06 +02001307 memset(&rp, 0, sizeof(rp));
1308
Johan Hedberg03811012010-12-08 00:21:06 +02001309 bacpy(&rp.bdaddr, &hdev->bdaddr);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001310
1311 rp.version = hdev->hci_ver;
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02001312 rp.manufacturer = cpu_to_le16(hdev->manufacturer);
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001313
1314 rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
1315 rp.current_settings = cpu_to_le32(get_current_settings(hdev));
1316
1317 memcpy(rp.dev_class, hdev->dev_class, 3);
Johan Hedberg03811012010-12-08 00:21:06 +02001318
1319 memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
Johan Hedberg27fcc362012-02-22 21:46:22 +02001320 memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
Johan Hedberg03811012010-12-08 00:21:06 +02001321
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001322 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001323
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001324 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
1325 sizeof(rp));
Johan Hedberg03811012010-12-08 00:21:06 +02001326}
1327
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001328static void mgmt_pending_free(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001329{
1330 sock_put(cmd->sk);
1331 kfree(cmd->param);
1332 kfree(cmd);
1333}
1334
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001335static struct mgmt_pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode,
1336 struct hci_dev *hdev,
1337 void *data, u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001338{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001339 struct mgmt_pending_cmd *cmd;
Johan Hedberg03811012010-12-08 00:21:06 +02001340
Johan Hedbergfca20012014-06-28 17:54:05 +03001341 cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001342 if (!cmd)
1343 return NULL;
1344
1345 cmd->opcode = opcode;
1346 cmd->index = hdev->id;
1347
Johan Hedberg323b0b82014-12-05 13:36:01 +02001348 cmd->param = kmemdup(data, len, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02001349 if (!cmd->param) {
1350 kfree(cmd);
1351 return NULL;
1352 }
1353
Johan Hedberg323b0b82014-12-05 13:36:01 +02001354 cmd->param_len = len;
Johan Hedberg03811012010-12-08 00:21:06 +02001355
1356 cmd->sk = sk;
1357 sock_hold(sk);
1358
1359 list_add(&cmd->list, &hdev->mgmt_pending);
1360
1361 return cmd;
1362}
1363
1364static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001365 void (*cb)(struct mgmt_pending_cmd *cmd,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03001366 void *data),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001367 void *data)
Johan Hedberg03811012010-12-08 00:21:06 +02001368{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001369 struct mgmt_pending_cmd *cmd, *tmp;
Johan Hedberg03811012010-12-08 00:21:06 +02001370
Andre Guedesa3d09352013-02-01 11:21:30 -03001371 list_for_each_entry_safe(cmd, tmp, &hdev->mgmt_pending, list) {
Johan Hedberg03811012010-12-08 00:21:06 +02001372 if (opcode > 0 && cmd->opcode != opcode)
1373 continue;
1374
1375 cb(cmd, data);
1376 }
1377}
1378
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001379static void mgmt_pending_remove(struct mgmt_pending_cmd *cmd)
Johan Hedberg03811012010-12-08 00:21:06 +02001380{
1381 list_del(&cmd->list);
1382 mgmt_pending_free(cmd);
1383}
1384
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001385static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
Johan Hedberg86805702011-11-11 16:18:52 +02001386{
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001387 __le32 settings = cpu_to_le32(get_current_settings(hdev));
Johan Hedberg86805702011-11-11 16:18:52 +02001388
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001389 return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
1390 sizeof(settings));
Johan Hedberg86805702011-11-11 16:18:52 +02001391}
1392
Marcel Holtmann1904a852015-01-11 13:50:44 -08001393static void clean_up_hci_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg8b064a32014-02-24 14:52:22 +02001394{
1395 BT_DBG("%s status 0x%02x", hdev->name, status);
1396
Johan Hedberga3172b72014-02-28 09:33:44 +02001397 if (hci_conn_count(hdev) == 0) {
1398 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001399 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberga3172b72014-02-28 09:33:44 +02001400 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001401}
1402
Johan Hedberg23a48092014-07-08 16:05:06 +03001403static bool hci_stop_discovery(struct hci_request *req)
Johan Hedberg21a60d32014-06-10 14:05:58 +03001404{
1405 struct hci_dev *hdev = req->hdev;
1406 struct hci_cp_remote_name_req_cancel cp;
1407 struct inquiry_entry *e;
1408
1409 switch (hdev->discovery.state) {
1410 case DISCOVERY_FINDING:
1411 if (test_bit(HCI_INQUIRY, &hdev->flags)) {
1412 hci_req_add(req, HCI_OP_INQUIRY_CANCEL, 0, NULL);
1413 } else {
1414 cancel_delayed_work(&hdev->le_scan_disable);
1415 hci_req_add_le_scan_disable(req);
1416 }
1417
Johan Hedberg23a48092014-07-08 16:05:06 +03001418 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001419
1420 case DISCOVERY_RESOLVING:
1421 e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY,
1422 NAME_PENDING);
1423 if (!e)
Johan Hedberg23a48092014-07-08 16:05:06 +03001424 break;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001425
1426 bacpy(&cp.bdaddr, &e->data.bdaddr);
1427 hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp),
1428 &cp);
1429
Johan Hedberg23a48092014-07-08 16:05:06 +03001430 return true;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001431
1432 default:
1433 /* Passive scanning */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001434 if (hci_dev_test_flag(hdev, HCI_LE_SCAN)) {
Johan Hedberg21a60d32014-06-10 14:05:58 +03001435 hci_req_add_le_scan_disable(req);
Johan Hedberg23a48092014-07-08 16:05:06 +03001436 return true;
1437 }
1438
Johan Hedberg21a60d32014-06-10 14:05:58 +03001439 break;
1440 }
Johan Hedberg23a48092014-07-08 16:05:06 +03001441
1442 return false;
Johan Hedberg21a60d32014-06-10 14:05:58 +03001443}
1444
Johan Hedberg8b064a32014-02-24 14:52:22 +02001445static int clean_up_hci_state(struct hci_dev *hdev)
1446{
1447 struct hci_request req;
1448 struct hci_conn *conn;
Johan Hedberg23a48092014-07-08 16:05:06 +03001449 bool discov_stopped;
1450 int err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001451
1452 hci_req_init(&req, hdev);
1453
1454 if (test_bit(HCI_ISCAN, &hdev->flags) ||
1455 test_bit(HCI_PSCAN, &hdev->flags)) {
1456 u8 scan = 0x00;
1457 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
1458 }
1459
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001460 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Johan Hedberg8b064a32014-02-24 14:52:22 +02001461 disable_advertising(&req);
1462
Johan Hedberg23a48092014-07-08 16:05:06 +03001463 discov_stopped = hci_stop_discovery(&req);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001464
1465 list_for_each_entry(conn, &hdev->conn_hash.list, list) {
1466 struct hci_cp_disconnect dc;
Johan Hedbergc9910d02014-02-27 14:35:12 +02001467 struct hci_cp_reject_conn_req rej;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001468
Johan Hedbergc9910d02014-02-27 14:35:12 +02001469 switch (conn->state) {
1470 case BT_CONNECTED:
1471 case BT_CONFIG:
1472 dc.handle = cpu_to_le16(conn->handle);
1473 dc.reason = 0x15; /* Terminated due to Power Off */
1474 hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc);
1475 break;
1476 case BT_CONNECT:
1477 if (conn->type == LE_LINK)
1478 hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL,
1479 0, NULL);
1480 else if (conn->type == ACL_LINK)
1481 hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL,
1482 6, &conn->dst);
1483 break;
1484 case BT_CONNECT2:
1485 bacpy(&rej.bdaddr, &conn->dst);
1486 rej.reason = 0x15; /* Terminated due to Power Off */
1487 if (conn->type == ACL_LINK)
1488 hci_req_add(&req, HCI_OP_REJECT_CONN_REQ,
1489 sizeof(rej), &rej);
1490 else if (conn->type == SCO_LINK)
1491 hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ,
1492 sizeof(rej), &rej);
1493 break;
1494 }
Johan Hedberg8b064a32014-02-24 14:52:22 +02001495 }
1496
Johan Hedberg23a48092014-07-08 16:05:06 +03001497 err = hci_req_run(&req, clean_up_hci_complete);
1498 if (!err && discov_stopped)
1499 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
1500
1501 return err;
Johan Hedberg8b064a32014-02-24 14:52:22 +02001502}
1503
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001504static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001505 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001506{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001507 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001508 struct mgmt_pending_cmd *cmd;
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001509 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02001510
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001511 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001512
Johan Hedberga7e80f22013-01-09 16:05:19 +02001513 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02001514 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1515 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001516
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001517 hci_dev_lock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001518
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001519 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001520 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
1521 MGMT_STATUS_BUSY);
Johan Hedberg87b95ba2013-09-25 13:26:06 +03001522 goto failed;
1523 }
1524
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001525 if (hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) {
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001526 cancel_delayed_work(&hdev->power_off);
1527
1528 if (cp->val) {
Johan Hedberga1d70452013-01-09 15:29:40 +02001529 mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev,
1530 data, len);
1531 err = mgmt_powered(hdev, 1);
Marcel Holtmannf0d4b782012-02-21 12:14:25 +01001532 goto failed;
1533 }
1534 }
1535
Johan Hedberg4b34ee782012-02-21 14:13:02 +02001536 if (!!cp->val == hdev_is_powered(hdev)) {
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001537 err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001538 goto failed;
1539 }
1540
Johan Hedberg03811012010-12-08 00:21:06 +02001541 cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
1542 if (!cmd) {
1543 err = -ENOMEM;
1544 goto failed;
1545 }
1546
Johan Hedberg8b064a32014-02-24 14:52:22 +02001547 if (cp->val) {
Johan Hedberg19202572013-01-14 22:33:51 +02001548 queue_work(hdev->req_workqueue, &hdev->power_on);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001549 err = 0;
1550 } else {
1551 /* Disconnect connections, stop scans, etc */
1552 err = clean_up_hci_state(hdev);
Johan Hedberga3172b72014-02-28 09:33:44 +02001553 if (!err)
1554 queue_delayed_work(hdev->req_workqueue, &hdev->power_off,
1555 HCI_POWER_OFF_TIMEOUT);
Johan Hedberg03811012010-12-08 00:21:06 +02001556
Johan Hedberg8b064a32014-02-24 14:52:22 +02001557 /* ENODATA means there were no HCI commands queued */
1558 if (err == -ENODATA) {
Johan Hedberga3172b72014-02-28 09:33:44 +02001559 cancel_delayed_work(&hdev->power_off);
Johan Hedberg8b064a32014-02-24 14:52:22 +02001560 queue_work(hdev->req_workqueue, &hdev->power_off.work);
1561 err = 0;
1562 }
1563 }
Johan Hedberg03811012010-12-08 00:21:06 +02001564
1565failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001566 hci_dev_unlock(hdev);
Johan Hedberg03811012010-12-08 00:21:06 +02001567 return err;
1568}
1569
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001570static int new_settings(struct hci_dev *hdev, struct sock *skip)
1571{
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001572 __le32 ev = cpu_to_le32(get_current_settings(hdev));
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001573
Marcel Holtmannf6b77122015-03-14 19:28:05 -07001574 return mgmt_generic_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
1575 sizeof(ev), skip);
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02001576}
1577
Johan Hedberg91a668b2014-07-09 13:28:26 +03001578int mgmt_new_settings(struct hci_dev *hdev)
1579{
1580 return new_settings(hdev, NULL);
1581}
1582
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001583struct cmd_lookup {
1584 struct sock *sk;
1585 struct hci_dev *hdev;
1586 u8 mgmt_status;
1587};
1588
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001589static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001590{
1591 struct cmd_lookup *match = data;
1592
1593 send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
1594
1595 list_del(&cmd->list);
1596
1597 if (match->sk == NULL) {
1598 match->sk = cmd->sk;
1599 sock_hold(match->sk);
1600 }
1601
1602 mgmt_pending_free(cmd);
1603}
1604
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001605static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001606{
1607 u8 *status = data;
1608
Johan Hedberga69e8372015-03-06 21:08:53 +02001609 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
Johan Hedbergbd99abd2013-09-25 13:26:07 +03001610 mgmt_pending_remove(cmd);
1611}
1612
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001613static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg1b9b5ee2014-12-05 13:36:00 +02001614{
1615 if (cmd->cmd_complete) {
1616 u8 *status = data;
1617
1618 cmd->cmd_complete(cmd, *status);
1619 mgmt_pending_remove(cmd);
1620
1621 return;
1622 }
1623
1624 cmd_status_rsp(cmd, data);
1625}
1626
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001627static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedbergf5818c22014-12-05 13:36:02 +02001628{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001629 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1630 cmd->param, cmd->param_len);
Johan Hedbergf5818c22014-12-05 13:36:02 +02001631}
1632
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001633static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001634{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02001635 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
1636 cmd->param, sizeof(struct mgmt_addr_info));
Johan Hedberg7776d1d2014-12-05 13:36:03 +02001637}
1638
Johan Hedberge6fe7982013-10-02 15:45:22 +03001639static u8 mgmt_bredr_support(struct hci_dev *hdev)
1640{
1641 if (!lmp_bredr_capable(hdev))
1642 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001643 else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001644 return MGMT_STATUS_REJECTED;
1645 else
1646 return MGMT_STATUS_SUCCESS;
1647}
1648
1649static u8 mgmt_le_support(struct hci_dev *hdev)
1650{
1651 if (!lmp_le_capable(hdev))
1652 return MGMT_STATUS_NOT_SUPPORTED;
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001653 else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberge6fe7982013-10-02 15:45:22 +03001654 return MGMT_STATUS_REJECTED;
1655 else
1656 return MGMT_STATUS_SUCCESS;
1657}
1658
Marcel Holtmann1904a852015-01-11 13:50:44 -08001659static void set_discoverable_complete(struct hci_dev *hdev, u8 status,
1660 u16 opcode)
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001661{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001662 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001663 struct mgmt_mode *cp;
Marcel Holtmann970ba522013-10-15 06:33:57 -07001664 struct hci_request req;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001665 bool changed;
1666
1667 BT_DBG("status 0x%02x", status);
1668
1669 hci_dev_lock(hdev);
1670
1671 cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
1672 if (!cmd)
1673 goto unlock;
1674
1675 if (status) {
1676 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001677 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001678 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001679 goto remove_cmd;
1680 }
1681
1682 cp = cmd->param;
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001683 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001684 changed = !hci_dev_test_and_set_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001685
1686 if (hdev->discov_timeout > 0) {
1687 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
1688 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
1689 to);
1690 }
1691 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001692 changed = hci_dev_test_and_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd4462a02013-10-15 08:11:02 -07001693 }
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001694
1695 send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
1696
1697 if (changed)
1698 new_settings(hdev, cmd->sk);
1699
Marcel Holtmann970ba522013-10-15 06:33:57 -07001700 /* When the discoverable mode gets changed, make sure
1701 * that class of device has the limited discoverable
Johan Hedberg432df052014-08-01 11:13:31 +03001702 * bit correctly set. Also update page scan based on whitelist
1703 * entries.
Marcel Holtmann970ba522013-10-15 06:33:57 -07001704 */
1705 hci_req_init(&req, hdev);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001706 __hci_update_page_scan(&req);
Marcel Holtmann970ba522013-10-15 06:33:57 -07001707 update_class(&req);
1708 hci_req_run(&req, NULL);
1709
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001710remove_cmd:
1711 mgmt_pending_remove(cmd);
1712
1713unlock:
1714 hci_dev_unlock(hdev);
1715}
1716
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001717static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001718 u16 len)
Johan Hedberg03811012010-12-08 00:21:06 +02001719{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001720 struct mgmt_cp_set_discoverable *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001721 struct mgmt_pending_cmd *cmd;
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001722 struct hci_request req;
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001723 u16 timeout;
Johan Hedberg9a43e252013-10-20 19:00:07 +03001724 u8 scan;
Johan Hedberg03811012010-12-08 00:21:06 +02001725 int err;
Johan Hedberge41d8b42010-12-13 21:07:03 +02001726
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001727 BT_DBG("request for %s", hdev->name);
Johan Hedberg03811012010-12-08 00:21:06 +02001728
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001729 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
1730 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02001731 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1732 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03001733
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001734 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02001735 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1736 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02001737
Marcel Holtmann1f350c82012-03-12 20:31:08 -07001738 timeout = __le16_to_cpu(cp->timeout);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001739
1740 /* Disabling discoverable requires that no timeout is set,
1741 * and enabling limited discoverable requires a timeout.
1742 */
1743 if ((cp->val == 0x00 && timeout > 0) ||
1744 (cp->val == 0x02 && timeout == 0))
Johan Hedberga69e8372015-03-06 21:08:53 +02001745 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1746 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001747
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001748 hci_dev_lock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001749
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001750 if (!hdev_is_powered(hdev) && timeout > 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001751 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1752 MGMT_STATUS_NOT_POWERED);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001753 goto failed;
1754 }
1755
1756 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03001757 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001758 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1759 MGMT_STATUS_BUSY);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001760 goto failed;
1761 }
1762
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001763 if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02001764 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
1765 MGMT_STATUS_REJECTED);
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001766 goto failed;
1767 }
1768
1769 if (!hdev_is_powered(hdev)) {
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001770 bool changed = false;
1771
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001772 /* Setting limited discoverable when powered off is
1773 * not a valid operation since it requires a timeout
1774 * and so no need to check HCI_LIMITED_DISCOVERABLE.
1775 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001776 if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07001777 hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001778 changed = true;
1779 }
1780
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001781 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedberg0224d2f2012-02-21 19:40:05 +02001782 if (err < 0)
1783 goto failed;
1784
1785 if (changed)
1786 err = new_settings(hdev, sk);
1787
Johan Hedberg5e5282b2012-02-21 16:01:30 +02001788 goto failed;
1789 }
1790
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001791 /* If the current mode is the same, then just update the timeout
1792 * value with the new value. And if only the timeout gets updated,
1793 * then no need for any HCI transactions.
1794 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001795 if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
1796 (cp->val == 0x02) == hci_dev_test_flag(hdev,
1797 HCI_LIMITED_DISCOVERABLE)) {
Marcel Holtmann36261542013-10-15 08:28:51 -07001798 cancel_delayed_work(&hdev->discov_off);
1799 hdev->discov_timeout = timeout;
Marcel Holtmann955638e2012-02-22 18:21:00 +01001800
Marcel Holtmann36261542013-10-15 08:28:51 -07001801 if (cp->val && hdev->discov_timeout > 0) {
1802 int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001803 queue_delayed_work(hdev->workqueue, &hdev->discov_off,
Marcel Holtmann36261542013-10-15 08:28:51 -07001804 to);
Marcel Holtmann955638e2012-02-22 18:21:00 +01001805 }
1806
Johan Hedberg69ab39e2011-12-15 00:47:35 +02001807 err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001808 goto failed;
1809 }
1810
1811 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
1812 if (!cmd) {
1813 err = -ENOMEM;
1814 goto failed;
1815 }
1816
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001817 /* Cancel any potential discoverable timeout that might be
1818 * still active and store new timeout value. The arming of
1819 * the timeout happens in the complete handler.
1820 */
1821 cancel_delayed_work(&hdev->discov_off);
1822 hdev->discov_timeout = timeout;
1823
Johan Hedbergb456f872013-10-19 23:38:22 +03001824 /* Limited discoverable mode */
1825 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001826 hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001827 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001828 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Johan Hedbergb456f872013-10-19 23:38:22 +03001829
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001830 hci_req_init(&req, hdev);
1831
Johan Hedberg9a43e252013-10-20 19:00:07 +03001832 /* The procedure for LE-only controllers is much simpler - just
1833 * update the advertising data.
1834 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001835 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg9a43e252013-10-20 19:00:07 +03001836 goto update_ad;
1837
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001838 scan = SCAN_PAGE;
1839
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001840 if (cp->val) {
1841 struct hci_cp_write_current_iac_lap hci_cp;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001842
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001843 if (cp->val == 0x02) {
1844 /* Limited discoverable mode */
Marcel Holtmann33337dc2013-10-23 08:28:01 -07001845 hci_cp.num_iac = min_t(u8, hdev->num_iac, 2);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001846 hci_cp.iac_lap[0] = 0x00; /* LIAC */
1847 hci_cp.iac_lap[1] = 0x8b;
1848 hci_cp.iac_lap[2] = 0x9e;
1849 hci_cp.iac_lap[3] = 0x33; /* GIAC */
1850 hci_cp.iac_lap[4] = 0x8b;
1851 hci_cp.iac_lap[5] = 0x9e;
1852 } else {
1853 /* General discoverable mode */
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001854 hci_cp.num_iac = 1;
1855 hci_cp.iac_lap[0] = 0x33; /* GIAC */
1856 hci_cp.iac_lap[1] = 0x8b;
1857 hci_cp.iac_lap[2] = 0x9e;
1858 }
1859
1860 hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
1861 (hci_cp.num_iac * 3) + 1, &hci_cp);
1862
1863 scan |= SCAN_INQUIRY;
1864 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001865 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
Marcel Holtmann310a3d42013-10-15 09:13:39 -07001866 }
1867
1868 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001869
Johan Hedberg9a43e252013-10-20 19:00:07 +03001870update_ad:
1871 update_adv_data(&req);
1872
Johan Hedbergbfaf8c92013-10-14 21:15:27 +03001873 err = hci_req_run(&req, set_discoverable_complete);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001874 if (err < 0)
1875 mgmt_pending_remove(cmd);
1876
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001877failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03001878 hci_dev_unlock(hdev);
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001879 return err;
1880}
1881
Johan Hedberg406d7802013-03-15 17:07:09 -05001882static void write_fast_connectable(struct hci_request *req, bool enable)
1883{
Johan Hedbergbd98b992013-03-15 17:07:13 -05001884 struct hci_dev *hdev = req->hdev;
Johan Hedberg406d7802013-03-15 17:07:09 -05001885 struct hci_cp_write_page_scan_activity acp;
1886 u8 type;
1887
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001888 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberg547003b2013-10-21 16:51:53 +03001889 return;
1890
Johan Hedberg4c01f8b2013-03-15 17:07:14 -05001891 if (hdev->hci_ver < BLUETOOTH_VER_1_2)
1892 return;
1893
Johan Hedberg406d7802013-03-15 17:07:09 -05001894 if (enable) {
1895 type = PAGE_SCAN_TYPE_INTERLACED;
1896
1897 /* 160 msec page scan interval */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001898 acp.interval = cpu_to_le16(0x0100);
Johan Hedberg406d7802013-03-15 17:07:09 -05001899 } else {
1900 type = PAGE_SCAN_TYPE_STANDARD; /* default */
1901
1902 /* default 1.28 sec page scan */
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001903 acp.interval = cpu_to_le16(0x0800);
Johan Hedberg406d7802013-03-15 17:07:09 -05001904 }
1905
Joe Perchesdcf4adb2014-03-12 10:52:35 -07001906 acp.window = cpu_to_le16(0x0012);
Johan Hedberg406d7802013-03-15 17:07:09 -05001907
Johan Hedbergbd98b992013-03-15 17:07:13 -05001908 if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval ||
1909 __cpu_to_le16(hdev->page_scan_window) != acp.window)
1910 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
1911 sizeof(acp), &acp);
1912
1913 if (hdev->page_scan_type != type)
1914 hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type);
Johan Hedberg406d7802013-03-15 17:07:09 -05001915}
1916
Marcel Holtmann1904a852015-01-11 13:50:44 -08001917static void set_connectable_complete(struct hci_dev *hdev, u8 status,
1918 u16 opcode)
Johan Hedberg2b76f452013-03-15 17:07:04 -05001919{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02001920 struct mgmt_pending_cmd *cmd;
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001921 struct mgmt_mode *cp;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001922 bool conn_changed, discov_changed;
Johan Hedberg2b76f452013-03-15 17:07:04 -05001923
1924 BT_DBG("status 0x%02x", status);
1925
1926 hci_dev_lock(hdev);
1927
1928 cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
1929 if (!cmd)
1930 goto unlock;
1931
Johan Hedberg37438c12013-10-14 16:20:05 +03001932 if (status) {
1933 u8 mgmt_err = mgmt_status(status);
Johan Hedberga69e8372015-03-06 21:08:53 +02001934 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg37438c12013-10-14 16:20:05 +03001935 goto remove_cmd;
1936 }
1937
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001938 cp = cmd->param;
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001939 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07001940 conn_changed = !hci_dev_test_and_set_flag(hdev,
1941 HCI_CONNECTABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001942 discov_changed = false;
1943 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07001944 conn_changed = hci_dev_test_and_clear_flag(hdev,
1945 HCI_CONNECTABLE);
1946 discov_changed = hci_dev_test_and_clear_flag(hdev,
1947 HCI_DISCOVERABLE);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001948 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001949
Johan Hedberg2b76f452013-03-15 17:07:04 -05001950 send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
1951
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001952 if (conn_changed || discov_changed) {
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001953 new_settings(hdev, cmd->sk);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001954 hci_update_page_scan(hdev);
Johan Hedbergbc6d2d02014-07-10 12:09:08 +03001955 if (discov_changed)
1956 mgmt_update_adv_data(hdev);
Johan Hedberg2b7be332014-07-07 14:40:22 +03001957 hci_update_background_scan(hdev);
1958 }
Johan Hedbergd7b856f2013-10-14 16:20:04 +03001959
Johan Hedberg37438c12013-10-14 16:20:05 +03001960remove_cmd:
Johan Hedberg2b76f452013-03-15 17:07:04 -05001961 mgmt_pending_remove(cmd);
1962
1963unlock:
1964 hci_dev_unlock(hdev);
1965}
1966
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001967static int set_connectable_update_settings(struct hci_dev *hdev,
1968 struct sock *sk, u8 val)
1969{
1970 bool changed = false;
1971 int err;
1972
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07001973 if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001974 changed = true;
1975
1976 if (val) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07001977 hci_dev_set_flag(hdev, HCI_CONNECTABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001978 } else {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07001979 hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
1980 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001981 }
1982
1983 err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
1984 if (err < 0)
1985 return err;
1986
Johan Hedberg562064e2014-07-08 16:35:34 +03001987 if (changed) {
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02001988 hci_update_page_scan(hdev);
Johan Hedberg562064e2014-07-08 16:35:34 +03001989 hci_update_background_scan(hdev);
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001990 return new_settings(hdev, sk);
Johan Hedberg562064e2014-07-08 16:35:34 +03001991 }
Johan Hedberge8ba3a12013-10-19 23:38:18 +03001992
1993 return 0;
1994}
1995
Johan Hedbergbdb6d972012-02-28 06:13:32 +02001996static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03001997 u16 len)
Johan Hedbergf7b64e692010-12-13 21:07:06 +02001998{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03001999 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002000 struct mgmt_pending_cmd *cmd;
Johan Hedberg2b76f452013-03-15 17:07:04 -05002001 struct hci_request req;
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002002 u8 scan;
Johan Hedbergf7b64e692010-12-13 21:07:06 +02002003 int err;
Johan Hedberg03811012010-12-08 00:21:06 +02002004
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002005 BT_DBG("request for %s", hdev->name);
Johan Hedberge41d8b42010-12-13 21:07:03 +02002006
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002007 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
2008 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002009 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2010 MGMT_STATUS_REJECTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002011
Johan Hedberga7e80f22013-01-09 16:05:19 +02002012 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002013 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2014 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002015
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002016 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002017
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002018 if (!hdev_is_powered(hdev)) {
Johan Hedberge8ba3a12013-10-19 23:38:18 +03002019 err = set_connectable_update_settings(hdev, sk, cp->val);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002020 goto failed;
2021 }
2022
2023 if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002024 mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002025 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
2026 MGMT_STATUS_BUSY);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002027 goto failed;
2028 }
2029
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002030 cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
2031 if (!cmd) {
2032 err = -ENOMEM;
2033 goto failed;
2034 }
2035
Johan Hedberg2b76f452013-03-15 17:07:04 -05002036 hci_req_init(&req, hdev);
2037
Johan Hedberg9a43e252013-10-20 19:00:07 +03002038 /* If BR/EDR is not enabled and we disable advertising as a
2039 * by-product of disabling connectable, we need to update the
2040 * advertising flags.
2041 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002042 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg9a43e252013-10-20 19:00:07 +03002043 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002044 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
2045 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Johan Hedberg9a43e252013-10-20 19:00:07 +03002046 }
2047 update_adv_data(&req);
2048 } else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
Johan Hedberg9b742462013-10-14 16:20:03 +03002049 if (cp->val) {
2050 scan = SCAN_PAGE;
2051 } else {
Johan Hedberg3bd27242014-07-28 20:53:58 +03002052 /* If we don't have any whitelist entries just
2053 * disable all scanning. If there are entries
2054 * and we had both page and inquiry scanning
2055 * enabled then fall back to only page scanning.
2056 * Otherwise no changes are needed.
2057 */
2058 if (list_empty(&hdev->whitelist))
2059 scan = SCAN_DISABLED;
2060 else if (test_bit(HCI_ISCAN, &hdev->flags))
2061 scan = SCAN_PAGE;
2062 else
2063 goto no_scan_update;
Johan Hedberg9b742462013-10-14 16:20:03 +03002064
2065 if (test_bit(HCI_ISCAN, &hdev->flags) &&
Marcel Holtmann8d6083f2013-10-14 16:38:45 -07002066 hdev->discov_timeout > 0)
Johan Hedberg9b742462013-10-14 16:20:03 +03002067 cancel_delayed_work(&hdev->discov_off);
2068 }
2069
2070 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
2071 }
Johan Hedberg2b76f452013-03-15 17:07:04 -05002072
Johan Hedberg3bd27242014-07-28 20:53:58 +03002073no_scan_update:
Johan Hedberge8b12022014-07-10 10:51:27 +03002074 /* Update the advertising parameters if necessary */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002075 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002076 enable_advertising(&req);
Johan Hedberg1987fdc2013-10-14 21:15:24 +03002077
Johan Hedberg2b76f452013-03-15 17:07:04 -05002078 err = hci_req_run(&req, set_connectable_complete);
Johan Hedberg9b742462013-10-14 16:20:03 +03002079 if (err < 0) {
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002080 mgmt_pending_remove(cmd);
Johan Hedberg9b742462013-10-14 16:20:03 +03002081 if (err == -ENODATA)
Johan Hedberga81070b2013-10-19 23:38:19 +03002082 err = set_connectable_update_settings(hdev, sk,
2083 cp->val);
Johan Hedberg9b742462013-10-14 16:20:03 +03002084 goto failed;
2085 }
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002086
2087failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002088 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002089 return err;
2090}
2091
Johan Hedbergb2939472014-07-30 09:22:23 +03002092static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002093 u16 len)
Johan Hedberg73f22f62010-12-29 16:00:25 +02002094{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002095 struct mgmt_mode *cp = data;
Marcel Holtmann55594352013-10-06 16:11:57 -07002096 bool changed;
Johan Hedberg73f22f62010-12-29 16:00:25 +02002097 int err;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002098
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002099 BT_DBG("request for %s", hdev->name);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002100
Johan Hedberga7e80f22013-01-09 16:05:19 +02002101 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002102 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
2103 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002104
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002105 hci_dev_lock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002106
2107 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07002108 changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002109 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002110 changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002111
Johan Hedbergb2939472014-07-30 09:22:23 +03002112 err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002113 if (err < 0)
Marcel Holtmann55594352013-10-06 16:11:57 -07002114 goto unlock;
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002115
Marcel Holtmann55594352013-10-06 16:11:57 -07002116 if (changed)
2117 err = new_settings(hdev, sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002118
Marcel Holtmann55594352013-10-06 16:11:57 -07002119unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002120 hci_dev_unlock(hdev);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02002121 return err;
2122}
Johan Hedberg72a734e2010-12-30 00:38:22 +02002123
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002124static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
2125 u16 len)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002126{
2127 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002128 struct mgmt_pending_cmd *cmd;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002129 u8 val, status;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002130 int err;
2131
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002132 BT_DBG("request for %s", hdev->name);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002133
Johan Hedberge6fe7982013-10-02 15:45:22 +03002134 status = mgmt_bredr_support(hdev);
2135 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002136 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2137 status);
Johan Hedberg33c525c2012-10-24 21:11:58 +03002138
Johan Hedberga7e80f22013-01-09 16:05:19 +02002139 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002140 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2141 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002142
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002143 hci_dev_lock(hdev);
2144
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002145 if (!hdev_is_powered(hdev)) {
Johan Hedberg47990ea2012-02-22 11:58:37 +02002146 bool changed = false;
2147
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002148 if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002149 hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02002150 changed = true;
2151 }
2152
2153 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2154 if (err < 0)
2155 goto failed;
2156
2157 if (changed)
2158 err = new_settings(hdev, sk);
2159
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002160 goto failed;
2161 }
2162
2163 if (mgmt_pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002164 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
2165 MGMT_STATUS_BUSY);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002166 goto failed;
2167 }
2168
2169 val = !!cp->val;
2170
2171 if (test_bit(HCI_AUTH, &hdev->flags) == val) {
2172 err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
2173 goto failed;
2174 }
2175
2176 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
2177 if (!cmd) {
2178 err = -ENOMEM;
2179 goto failed;
2180 }
2181
2182 err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
2183 if (err < 0) {
2184 mgmt_pending_remove(cmd);
2185 goto failed;
2186 }
2187
2188failed:
2189 hci_dev_unlock(hdev);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02002190 return err;
2191}
2192
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002193static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002194{
2195 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002196 struct mgmt_pending_cmd *cmd;
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002197 u8 status;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002198 int err;
2199
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002200 BT_DBG("request for %s", hdev->name);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002201
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002202 status = mgmt_bredr_support(hdev);
2203 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002204 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
Marcel Holtmanncdba5282013-10-02 21:31:52 -07002205
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002206 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002207 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2208 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002209
Johan Hedberga7e80f22013-01-09 16:05:19 +02002210 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002211 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2212 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002213
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002214 hci_dev_lock(hdev);
Johan Hedberg6c8f12c2012-02-22 16:35:26 +02002215
Johan Hedberg4b34ee782012-02-21 14:13:02 +02002216 if (!hdev_is_powered(hdev)) {
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002217 bool changed;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002218
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002219 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002220 changed = !hci_dev_test_and_set_flag(hdev,
2221 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002222 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002223 changed = hci_dev_test_and_clear_flag(hdev,
2224 HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002225 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002226 changed = hci_dev_test_and_clear_flag(hdev,
2227 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002228 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002229 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02002230 }
2231
2232 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2233 if (err < 0)
2234 goto failed;
2235
2236 if (changed)
2237 err = new_settings(hdev, sk);
2238
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002239 goto failed;
2240 }
2241
Johan Hedberg94d52da2015-02-19 17:38:06 +02002242 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002243 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
2244 MGMT_STATUS_BUSY);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002245 goto failed;
2246 }
2247
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002248 if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002249 err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
2250 goto failed;
2251 }
2252
2253 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
2254 if (!cmd) {
2255 err = -ENOMEM;
2256 goto failed;
2257 }
2258
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002259 if (!cp->val && hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03002260 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
2261 sizeof(cp->val), &cp->val);
2262
Marcel Holtmann72ef0c12013-10-10 03:08:10 -07002263 err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002264 if (err < 0) {
2265 mgmt_pending_remove(cmd);
2266 goto failed;
2267 }
2268
2269failed:
2270 hci_dev_unlock(hdev);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02002271 return err;
2272}
2273
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002274static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002275{
2276 struct mgmt_mode *cp = data;
Marcel Holtmannee392692013-10-01 22:59:23 -07002277 bool changed;
Johan Hedberge6fe7982013-10-02 15:45:22 +03002278 u8 status;
Marcel Holtmannee392692013-10-01 22:59:23 -07002279 int err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002280
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002281 BT_DBG("request for %s", hdev->name);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002282
Johan Hedberge6fe7982013-10-02 15:45:22 +03002283 status = mgmt_bredr_support(hdev);
2284 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02002285 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002286
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002287 if (!lmp_ssp_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002288 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2289 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002290
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002291 if (!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002292 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2293 MGMT_STATUS_REJECTED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07002294
Johan Hedberga7e80f22013-01-09 16:05:19 +02002295 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002296 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2297 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002298
Marcel Holtmannee392692013-10-01 22:59:23 -07002299 hci_dev_lock(hdev);
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002300
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002301 if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002302 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2303 MGMT_STATUS_BUSY);
Johan Hedberga2cb01d2015-02-19 17:38:07 +02002304 goto unlock;
2305 }
2306
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002307 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07002308 changed = !hci_dev_test_and_set_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002309 } else {
2310 if (hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002311 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
2312 MGMT_STATUS_REJECTED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002313 goto unlock;
2314 }
2315
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002316 changed = hci_dev_test_and_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmanna0cdf9602013-10-02 00:27:02 -07002317 }
Marcel Holtmannee392692013-10-01 22:59:23 -07002318
2319 err = send_settings_rsp(sk, MGMT_OP_SET_HS, hdev);
2320 if (err < 0)
2321 goto unlock;
2322
2323 if (changed)
2324 err = new_settings(hdev, sk);
2325
2326unlock:
2327 hci_dev_unlock(hdev);
2328 return err;
Johan Hedberg6d80dfd2012-02-20 23:50:38 +02002329}
2330
Marcel Holtmann1904a852015-01-11 13:50:44 -08002331static void le_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002332{
2333 struct cmd_lookup match = { NULL, hdev };
2334
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302335 hci_dev_lock(hdev);
2336
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002337 if (status) {
2338 u8 mgmt_err = mgmt_status(status);
2339
2340 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
2341 &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302342 goto unlock;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002343 }
2344
2345 mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
2346
2347 new_settings(hdev, match.sk);
2348
2349 if (match.sk)
2350 sock_put(match.sk);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002351
2352 /* Make sure the controller has a good default for
2353 * advertising data. Restrict the update to when LE
2354 * has actually been enabled. During power on, the
2355 * update in powered_update_hci will take care of it.
2356 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002357 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002358 struct hci_request req;
2359
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002360 hci_req_init(&req, hdev);
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07002361 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07002362 update_scan_rsp_data(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02002363 __hci_update_background_scan(&req);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002364 hci_req_run(&req, NULL);
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002365 }
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05302366
2367unlock:
2368 hci_dev_unlock(hdev);
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002369}
2370
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002371static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002372{
2373 struct mgmt_mode *cp = data;
2374 struct hci_cp_write_le_host_supported hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002375 struct mgmt_pending_cmd *cmd;
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002376 struct hci_request req;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002377 int err;
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002378 u8 val, enabled;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002379
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002380 BT_DBG("request for %s", hdev->name);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002381
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002382 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002383 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2384 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002385
Johan Hedberga7e80f22013-01-09 16:05:19 +02002386 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002387 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2388 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02002389
Johan Hedbergc73eee92013-04-19 18:35:21 +03002390 /* LE-only devices do not allow toggling LE on/off */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002391 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02002392 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2393 MGMT_STATUS_REJECTED);
Johan Hedbergc73eee92013-04-19 18:35:21 +03002394
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002395 hci_dev_lock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002396
2397 val = !!cp->val;
Gustavo Padovanffa88e02012-11-23 16:50:51 -02002398 enabled = lmp_host_le_capable(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002399
Johan Hedberg0b60eba2012-02-28 00:57:24 +02002400 if (!hdev_is_powered(hdev) || val == enabled) {
Johan Hedberg06199cf2012-02-22 16:37:11 +02002401 bool changed = false;
2402
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002403 if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07002404 hci_dev_change_flag(hdev, HCI_LE_ENABLED);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002405 changed = true;
2406 }
2407
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002408 if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07002409 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03002410 changed = true;
2411 }
2412
Johan Hedberg06199cf2012-02-22 16:37:11 +02002413 err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
2414 if (err < 0)
Johan Hedberg1de028c2012-02-29 19:55:35 -08002415 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002416
2417 if (changed)
2418 err = new_settings(hdev, sk);
2419
Johan Hedberg1de028c2012-02-29 19:55:35 -08002420 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002421 }
2422
Johan Hedberg4375f102013-09-25 13:26:10 +03002423 if (mgmt_pending_find(MGMT_OP_SET_LE, hdev) ||
2424 mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002425 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
2426 MGMT_STATUS_BUSY);
Johan Hedberg1de028c2012-02-29 19:55:35 -08002427 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002428 }
2429
2430 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
2431 if (!cmd) {
2432 err = -ENOMEM;
Johan Hedberg1de028c2012-02-29 19:55:35 -08002433 goto unlock;
Johan Hedberg06199cf2012-02-22 16:37:11 +02002434 }
2435
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002436 hci_req_init(&req, hdev);
2437
Johan Hedberg06199cf2012-02-22 16:37:11 +02002438 memset(&hci_cp, 0, sizeof(hci_cp));
2439
2440 if (val) {
2441 hci_cp.le = val;
Marcel Holtmann32226e42014-07-24 20:04:16 +02002442 hci_cp.simul = 0x00;
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002443 } else {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07002444 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07002445 disable_advertising(&req);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002446 }
2447
Johan Hedberg416a4ae2013-09-25 13:26:08 +03002448 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
2449 &hci_cp);
2450
2451 err = hci_req_run(&req, le_enable_complete);
Syam Sidhardhan0c01bc42012-04-12 20:33:21 +05302452 if (err < 0)
Johan Hedberg06199cf2012-02-22 16:37:11 +02002453 mgmt_pending_remove(cmd);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002454
Johan Hedberg1de028c2012-02-29 19:55:35 -08002455unlock:
2456 hci_dev_unlock(hdev);
Johan Hedberg06199cf2012-02-22 16:37:11 +02002457 return err;
2458}
2459
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002460/* This is a helper function to test for pending mgmt commands that can
2461 * cause CoD or EIR HCI commands. We can only allow one such pending
2462 * mgmt command at a time since otherwise we cannot easily track what
2463 * the current values are, will be, and based on that calculate if a new
2464 * HCI command needs to be sent and if yes with what value.
2465 */
2466static bool pending_eir_or_class(struct hci_dev *hdev)
2467{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002468 struct mgmt_pending_cmd *cmd;
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002469
2470 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
2471 switch (cmd->opcode) {
2472 case MGMT_OP_ADD_UUID:
2473 case MGMT_OP_REMOVE_UUID:
2474 case MGMT_OP_SET_DEV_CLASS:
2475 case MGMT_OP_SET_POWERED:
2476 return true;
2477 }
2478 }
2479
2480 return false;
2481}
2482
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002483static const u8 bluetooth_base_uuid[] = {
2484 0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
2485 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2486};
2487
2488static u8 get_uuid_size(const u8 *uuid)
2489{
2490 u32 val;
2491
2492 if (memcmp(uuid, bluetooth_base_uuid, 12))
2493 return 128;
2494
2495 val = get_unaligned_le32(&uuid[12]);
2496 if (val > 0xffff)
2497 return 32;
2498
2499 return 16;
2500}
2501
Johan Hedberg92da6092013-03-15 17:06:55 -05002502static void mgmt_class_complete(struct hci_dev *hdev, u16 mgmt_op, u8 status)
2503{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002504 struct mgmt_pending_cmd *cmd;
Johan Hedberg92da6092013-03-15 17:06:55 -05002505
2506 hci_dev_lock(hdev);
2507
2508 cmd = mgmt_pending_find(mgmt_op, hdev);
2509 if (!cmd)
2510 goto unlock;
2511
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002512 mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
2513 mgmt_status(status), hdev->dev_class, 3);
Johan Hedberg92da6092013-03-15 17:06:55 -05002514
2515 mgmt_pending_remove(cmd);
2516
2517unlock:
2518 hci_dev_unlock(hdev);
2519}
2520
Marcel Holtmann1904a852015-01-11 13:50:44 -08002521static void add_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002522{
2523 BT_DBG("status 0x%02x", status);
2524
2525 mgmt_class_complete(hdev, MGMT_OP_ADD_UUID, status);
2526}
2527
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002528static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002529{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002530 struct mgmt_cp_add_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002531 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002532 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002533 struct bt_uuid *uuid;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002534 int err;
2535
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002536 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002537
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002538 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002539
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002540 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002541 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
2542 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002543 goto failed;
2544 }
2545
Andre Guedes92c4c202012-06-07 19:05:44 -03002546 uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002547 if (!uuid) {
2548 err = -ENOMEM;
2549 goto failed;
2550 }
2551
2552 memcpy(uuid->uuid, cp->uuid, 16);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002553 uuid->svc_hint = cp->svc_hint;
Johan Hedberg83be8ec2013-01-27 00:31:29 +02002554 uuid->size = get_uuid_size(cp->uuid);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002555
Johan Hedbergde66aa62013-01-27 00:31:27 +02002556 list_add_tail(&uuid->list, &hdev->uuids);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002557
Johan Hedberg890ea892013-03-15 17:06:52 -05002558 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002559
Johan Hedberg890ea892013-03-15 17:06:52 -05002560 update_class(&req);
2561 update_eir(&req);
2562
Johan Hedberg92da6092013-03-15 17:06:55 -05002563 err = hci_req_run(&req, add_uuid_complete);
2564 if (err < 0) {
2565 if (err != -ENODATA)
2566 goto failed;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002567
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002568 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_UUID, 0,
2569 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002570 goto failed;
2571 }
2572
2573 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002574 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002575 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002576 goto failed;
2577 }
2578
2579 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002580
2581failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002582 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002583 return err;
2584}
2585
Johan Hedberg24b78d02012-02-23 23:24:30 +02002586static bool enable_service_cache(struct hci_dev *hdev)
2587{
2588 if (!hdev_is_powered(hdev))
2589 return false;
2590
Marcel Holtmann238be782015-03-13 02:11:06 -07002591 if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg46818ed2013-01-14 22:33:52 +02002592 queue_delayed_work(hdev->workqueue, &hdev->service_cache,
2593 CACHE_TIMEOUT);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002594 return true;
2595 }
2596
2597 return false;
2598}
2599
Marcel Holtmann1904a852015-01-11 13:50:44 -08002600static void remove_uuid_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002601{
2602 BT_DBG("status 0x%02x", status);
2603
2604 mgmt_class_complete(hdev, MGMT_OP_REMOVE_UUID, status);
2605}
2606
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002607static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002608 u16 len)
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002609{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002610 struct mgmt_cp_remove_uuid *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002611 struct mgmt_pending_cmd *cmd;
Johan Hedberg056341c2013-01-27 00:31:30 +02002612 struct bt_uuid *match, *tmp;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002613 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 -05002614 struct hci_request req;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002615 int err, found;
2616
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002617 BT_DBG("request for %s", hdev->name);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002618
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002619 hci_dev_lock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002620
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002621 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002622 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2623 MGMT_STATUS_BUSY);
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02002624 goto unlock;
2625 }
2626
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002627 if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
Johan Hedberg35f74982014-02-18 17:14:32 +02002628 hci_uuids_clear(hdev);
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002629
Johan Hedberg24b78d02012-02-23 23:24:30 +02002630 if (enable_service_cache(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002631 err = mgmt_cmd_complete(sk, hdev->id,
2632 MGMT_OP_REMOVE_UUID,
2633 0, hdev->dev_class, 3);
Johan Hedberg24b78d02012-02-23 23:24:30 +02002634 goto unlock;
2635 }
Johan Hedberg4004b6d2012-02-23 21:30:12 +02002636
Johan Hedberg9246a862012-02-23 21:33:16 +02002637 goto update_class;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002638 }
2639
2640 found = 0;
2641
Johan Hedberg056341c2013-01-27 00:31:30 +02002642 list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002643 if (memcmp(match->uuid, cp->uuid, 16) != 0)
2644 continue;
2645
2646 list_del(&match->list);
Johan Hedberg482049f2012-11-08 10:25:26 +01002647 kfree(match);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002648 found++;
2649 }
2650
2651 if (found == 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002652 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
2653 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002654 goto unlock;
2655 }
2656
Johan Hedberg9246a862012-02-23 21:33:16 +02002657update_class:
Johan Hedberg890ea892013-03-15 17:06:52 -05002658 hci_req_init(&req, hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002659
Johan Hedberg890ea892013-03-15 17:06:52 -05002660 update_class(&req);
2661 update_eir(&req);
2662
Johan Hedberg92da6092013-03-15 17:06:55 -05002663 err = hci_req_run(&req, remove_uuid_complete);
2664 if (err < 0) {
2665 if (err != -ENODATA)
2666 goto unlock;
Johan Hedberg80a1e1d2011-03-28 14:07:23 +03002667
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002668 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, 0,
2669 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002670 goto unlock;
2671 }
2672
2673 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002674 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002675 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002676 goto unlock;
2677 }
2678
2679 err = 0;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002680
2681unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002682 hci_dev_unlock(hdev);
Johan Hedberg2aeb9a12011-01-04 12:08:51 +02002683 return err;
2684}
2685
Marcel Holtmann1904a852015-01-11 13:50:44 -08002686static void set_class_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg92da6092013-03-15 17:06:55 -05002687{
2688 BT_DBG("status 0x%02x", status);
2689
2690 mgmt_class_complete(hdev, MGMT_OP_SET_DEV_CLASS, status);
2691}
2692
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002693static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002694 u16 len)
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002695{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002696 struct mgmt_cp_set_dev_class *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002697 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05002698 struct hci_request req;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002699 int err;
2700
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002701 BT_DBG("request for %s", hdev->name);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002702
Marcel Holtmann6203fc92013-10-02 23:37:29 -07002703 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002704 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2705 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg13ecd8b2013-01-09 15:29:38 +02002706
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002707 hci_dev_lock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002708
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002709 if (pending_eir_or_class(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002710 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2711 MGMT_STATUS_BUSY);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002712 goto unlock;
2713 }
2714
2715 if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02002716 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
2717 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0cab9c82013-03-15 17:06:54 -05002718 goto unlock;
2719 }
2720
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002721 hdev->major_class = cp->major;
2722 hdev->minor_class = cp->minor;
2723
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002724 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002725 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2726 hdev->dev_class, 3);
Johan Hedberg932f5ff2012-02-22 22:11:32 +02002727 goto unlock;
2728 }
2729
Johan Hedberg890ea892013-03-15 17:06:52 -05002730 hci_req_init(&req, hdev);
2731
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002732 if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
Johan Hedberg7d785252011-12-15 00:47:39 +02002733 hci_dev_unlock(hdev);
2734 cancel_delayed_work_sync(&hdev->service_cache);
2735 hci_dev_lock(hdev);
Johan Hedberg890ea892013-03-15 17:06:52 -05002736 update_eir(&req);
Johan Hedberg7d785252011-12-15 00:47:39 +02002737 }
Johan Hedberg14c0b602011-12-15 00:47:37 +02002738
Johan Hedberg890ea892013-03-15 17:06:52 -05002739 update_class(&req);
2740
Johan Hedberg92da6092013-03-15 17:06:55 -05002741 err = hci_req_run(&req, set_class_complete);
2742 if (err < 0) {
2743 if (err != -ENODATA)
2744 goto unlock;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002745
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002746 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
2747 hdev->dev_class, 3);
Johan Hedberg90e70452012-02-23 23:09:40 +02002748 goto unlock;
2749 }
2750
2751 cmd = mgmt_pending_add(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
Johan Hedberg890ea892013-03-15 17:06:52 -05002752 if (!cmd) {
Johan Hedberg90e70452012-02-23 23:09:40 +02002753 err = -ENOMEM;
Johan Hedberg890ea892013-03-15 17:06:52 -05002754 goto unlock;
2755 }
2756
2757 err = 0;
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002758
Johan Hedbergb5235a62012-02-21 14:32:24 +02002759unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002760 hci_dev_unlock(hdev);
Johan Hedberg1aff6f02011-01-13 21:56:52 +02002761 return err;
2762}
2763
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002764static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002765 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002766{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002767 struct mgmt_cp_load_link_keys *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03002768 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
2769 sizeof(struct mgmt_link_key_info));
Szymon Janc4e51eae2011-02-25 19:05:48 +01002770 u16 key_count, expected_len;
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002771 bool changed;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002772 int i;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002773
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002774 BT_DBG("request for %s", hdev->name);
2775
2776 if (!lmp_bredr_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02002777 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2778 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9060d5c2013-10-02 21:16:07 -07002779
Marcel Holtmann1f350c82012-03-12 20:31:08 -07002780 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002781 if (key_count > max_key_count) {
2782 BT_ERR("load_link_keys: too big key_count value %u",
2783 key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02002784 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2785 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03002786 }
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002787
Johan Hedberg86742e12011-11-07 23:13:38 +02002788 expected_len = sizeof(*cp) + key_count *
2789 sizeof(struct mgmt_link_key_info);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002790 if (expected_len != len) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002791 BT_ERR("load_link_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02002792 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02002793 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2794 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002795 }
2796
Johan Hedberg4ae14302013-01-20 14:27:13 +02002797 if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02002798 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
2799 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ae14302013-01-20 14:27:13 +02002800
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002801 BT_DBG("%s debug_keys %u key_count %u", hdev->name, cp->debug_keys,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03002802 key_count);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002803
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002804 for (i = 0; i < key_count; i++) {
2805 struct mgmt_link_key_info *key = &cp->keys[i];
2806
Marcel Holtmann8e991132014-01-10 02:07:25 -08002807 if (key->addr.type != BDADDR_BREDR || key->type > 0x08)
Johan Hedberga69e8372015-03-06 21:08:53 +02002808 return mgmt_cmd_status(sk, hdev->id,
2809 MGMT_OP_LOAD_LINK_KEYS,
2810 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002811 }
2812
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002813 hci_dev_lock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002814
2815 hci_link_keys_clear(hdev);
2816
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002817 if (cp->debug_keys)
Marcel Holtmann238be782015-03-13 02:11:06 -07002818 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002819 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07002820 changed = hci_dev_test_and_clear_flag(hdev,
2821 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmannb1de97d2014-01-31 11:55:21 -08002822
2823 if (changed)
2824 new_settings(hdev, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002825
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002826 for (i = 0; i < key_count; i++) {
Johan Hedberg86742e12011-11-07 23:13:38 +02002827 struct mgmt_link_key_info *key = &cp->keys[i];
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002828
Johan Hedberg58e92932014-06-24 14:00:26 +03002829 /* Always ignore debug keys and require a new pairing if
2830 * the user wants to use them.
2831 */
2832 if (key->type == HCI_LK_DEBUG_COMBINATION)
2833 continue;
2834
Johan Hedberg7652ff62014-06-24 13:15:49 +03002835 hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
2836 key->type, key->pin_len, NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002837 }
2838
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002839 mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
Johan Hedberg0e5f8752011-11-11 16:18:54 +02002840
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002841 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002842
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03002843 return 0;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002844}
2845
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002846static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002847 u8 addr_type, struct sock *skip_sk)
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002848{
2849 struct mgmt_ev_device_unpaired ev;
2850
2851 bacpy(&ev.addr.bdaddr, bdaddr);
2852 ev.addr.type = addr_type;
2853
2854 return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002855 skip_sk);
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002856}
2857
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002858static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002859 u16 len)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002860{
Johan Hedberg124f6e32012-02-09 13:50:12 +02002861 struct mgmt_cp_unpair_device *cp = data;
2862 struct mgmt_rp_unpair_device rp;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002863 struct hci_cp_disconnect dc;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002864 struct mgmt_pending_cmd *cmd;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002865 struct hci_conn *conn;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002866 int err;
2867
Johan Hedberga8a1d192011-11-10 15:54:38 +02002868 memset(&rp, 0, sizeof(rp));
Johan Hedberg124f6e32012-02-09 13:50:12 +02002869 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2870 rp.addr.type = cp->addr.type;
Johan Hedberga8a1d192011-11-10 15:54:38 +02002871
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002872 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002873 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2874 MGMT_STATUS_INVALID_PARAMS,
2875 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002876
Johan Hedberg118da702013-01-20 14:27:20 +02002877 if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002878 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2879 MGMT_STATUS_INVALID_PARAMS,
2880 &rp, sizeof(rp));
Johan Hedberg118da702013-01-20 14:27:20 +02002881
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002882 hci_dev_lock(hdev);
2883
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002884 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002885 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2886 MGMT_STATUS_NOT_POWERED, &rp,
2887 sizeof(rp));
Johan Hedberg86a8cfc2012-02-22 22:53:34 +02002888 goto unlock;
2889 }
2890
Johan Hedberge0b2b272014-02-18 17:14:31 +02002891 if (cp->addr.type == BDADDR_BREDR) {
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002892 /* If disconnection is requested, then look up the
2893 * connection. If the remote device is connected, it
2894 * will be later used to terminate the link.
2895 *
2896 * Setting it to NULL explicitly will cause no
2897 * termination of the link.
2898 */
2899 if (cp->disconnect)
2900 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
2901 &cp->addr.bdaddr);
2902 else
2903 conn = NULL;
2904
Johan Hedberg124f6e32012-02-09 13:50:12 +02002905 err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
Johan Hedberge0b2b272014-02-18 17:14:31 +02002906 } else {
2907 u8 addr_type;
2908
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002909 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
2910 &cp->addr.bdaddr);
2911 if (conn) {
2912 /* Defer clearing up the connection parameters
2913 * until closing to give a chance of keeping
2914 * them if a repairing happens.
2915 */
2916 set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
2917
2918 /* If disconnection is not requested, then
2919 * clear the connection variable so that the
2920 * link is not terminated.
2921 */
2922 if (!cp->disconnect)
2923 conn = NULL;
2924 }
2925
Johan Hedberge0b2b272014-02-18 17:14:31 +02002926 if (cp->addr.type == BDADDR_LE_PUBLIC)
2927 addr_type = ADDR_LE_DEV_PUBLIC;
2928 else
2929 addr_type = ADDR_LE_DEV_RANDOM;
2930
Johan Hedberga7ec7332014-02-18 17:14:35 +02002931 hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
2932
Johan Hedberge0b2b272014-02-18 17:14:31 +02002933 err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
2934 }
Vinicius Costa Gomesb0dbfb42012-02-02 21:08:03 -03002935
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002936 if (err < 0) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002937 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
2938 MGMT_STATUS_NOT_PAIRED, &rp,
2939 sizeof(rp));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002940 goto unlock;
2941 }
2942
Alfonso Acosta89cbb062014-10-11 21:44:47 +00002943 /* If the connection variable is set, then termination of the
2944 * link is requested.
2945 */
Johan Hedberga8a1d192011-11-10 15:54:38 +02002946 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002947 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
2948 &rp, sizeof(rp));
Johan Hedbergb1078ad2012-02-09 17:21:16 +02002949 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002950 goto unlock;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002951 }
2952
Johan Hedberg124f6e32012-02-09 13:50:12 +02002953 cmd = mgmt_pending_add(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002954 sizeof(*cp));
Johan Hedberga8a1d192011-11-10 15:54:38 +02002955 if (!cmd) {
2956 err = -ENOMEM;
2957 goto unlock;
2958 }
2959
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02002960 cmd->cmd_complete = addr_cmd_complete;
2961
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02002962 dc.handle = cpu_to_le16(conn->handle);
Johan Hedberga8a1d192011-11-10 15:54:38 +02002963 dc.reason = 0x13; /* Remote User Terminated Connection */
2964 err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
2965 if (err < 0)
2966 mgmt_pending_remove(cmd);
2967
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002968unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002969 hci_dev_unlock(hdev);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02002970 return err;
2971}
2972
Johan Hedbergbdb6d972012-02-28 06:13:32 +02002973static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03002974 u16 len)
Johan Hedberg8962ee72011-01-20 12:40:27 +02002975{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03002976 struct mgmt_cp_disconnect *cp = data;
Johan Hedberg06a63b12013-01-20 14:27:21 +02002977 struct mgmt_rp_disconnect rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02002978 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002979 struct hci_conn *conn;
Johan Hedberg8962ee72011-01-20 12:40:27 +02002980 int err;
2981
2982 BT_DBG("");
2983
Johan Hedberg06a63b12013-01-20 14:27:21 +02002984 memset(&rp, 0, sizeof(rp));
2985 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
2986 rp.addr.type = cp->addr.type;
2987
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002988 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002989 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2990 MGMT_STATUS_INVALID_PARAMS,
2991 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02002992
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03002993 hci_dev_lock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02002994
2995 if (!test_bit(HCI_UP, &hdev->flags)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02002996 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
2997 MGMT_STATUS_NOT_POWERED, &rp,
2998 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02002999 goto failed;
3000 }
3001
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003002 if (mgmt_pending_find(MGMT_OP_DISCONNECT, hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003003 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3004 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003005 goto failed;
3006 }
3007
Andre Guedes591f47f2012-04-24 21:02:49 -03003008 if (cp->addr.type == BDADDR_BREDR)
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03003009 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
3010 &cp->addr.bdaddr);
Johan Hedberg88c3df12012-02-09 14:27:38 +02003011 else
3012 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
Vinicius Costa Gomes365227e2011-05-06 18:41:44 -03003013
Vishal Agarwalf9607272012-06-13 05:32:43 +05303014 if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003015 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
3016 MGMT_STATUS_NOT_CONNECTED, &rp,
3017 sizeof(rp));
Johan Hedberg8962ee72011-01-20 12:40:27 +02003018 goto failed;
3019 }
3020
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003021 cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003022 if (!cmd) {
3023 err = -ENOMEM;
Johan Hedberg8962ee72011-01-20 12:40:27 +02003024 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003025 }
Johan Hedberg8962ee72011-01-20 12:40:27 +02003026
Johan Hedbergf5818c22014-12-05 13:36:02 +02003027 cmd->cmd_complete = generic_cmd_complete;
3028
Johan Hedberge3f2f922014-08-18 20:33:33 +03003029 err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003030 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003031 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003032
3033failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003034 hci_dev_unlock(hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02003035 return err;
3036}
3037
Andre Guedes57c14772012-04-24 21:02:50 -03003038static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003039{
3040 switch (link_type) {
3041 case LE_LINK:
Johan Hedberg48264f02011-11-09 13:58:58 +02003042 switch (addr_type) {
3043 case ADDR_LE_DEV_PUBLIC:
Andre Guedes591f47f2012-04-24 21:02:49 -03003044 return BDADDR_LE_PUBLIC;
Andre Guedes0ed09142012-04-03 08:46:54 -03003045
Johan Hedberg48264f02011-11-09 13:58:58 +02003046 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003047 /* Fallback to LE Random address type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003048 return BDADDR_LE_RANDOM;
Johan Hedberg48264f02011-11-09 13:58:58 +02003049 }
Andre Guedes0ed09142012-04-03 08:46:54 -03003050
Johan Hedberg4c659c32011-11-07 23:13:39 +02003051 default:
Andre Guedes0ed09142012-04-03 08:46:54 -03003052 /* Fallback to BR/EDR type */
Andre Guedes591f47f2012-04-24 21:02:49 -03003053 return BDADDR_BREDR;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003054 }
3055}
3056
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003057static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
3058 u16 data_len)
Johan Hedberg2784eb42011-01-21 13:56:35 +02003059{
Johan Hedberg2784eb42011-01-21 13:56:35 +02003060 struct mgmt_rp_get_connections *rp;
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +02003061 struct hci_conn *c;
Johan Hedberga38528f2011-01-22 06:46:43 +02003062 size_t rp_len;
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003063 int err;
3064 u16 i;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003065
3066 BT_DBG("");
3067
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003068 hci_dev_lock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003069
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003070 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003071 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
3072 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003073 goto unlock;
3074 }
3075
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003076 i = 0;
Johan Hedbergb644ba32012-01-17 21:48:47 +02003077 list_for_each_entry(c, &hdev->conn_hash.list, list) {
3078 if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003079 i++;
Johan Hedberg2784eb42011-01-21 13:56:35 +02003080 }
3081
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003082 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Andre Guedes92c4c202012-06-07 19:05:44 -03003083 rp = kmalloc(rp_len, GFP_KERNEL);
Johan Hedberga38528f2011-01-22 06:46:43 +02003084 if (!rp) {
Johan Hedberg2784eb42011-01-21 13:56:35 +02003085 err = -ENOMEM;
3086 goto unlock;
3087 }
3088
Johan Hedberg2784eb42011-01-21 13:56:35 +02003089 i = 0;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003090 list_for_each_entry(c, &hdev->conn_hash.list, list) {
Johan Hedbergb644ba32012-01-17 21:48:47 +02003091 if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
3092 continue;
Johan Hedberg4c659c32011-11-07 23:13:39 +02003093 bacpy(&rp->addr[i].bdaddr, &c->dst);
Andre Guedes57c14772012-04-24 21:02:50 -03003094 rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
Andre Guedes0ed09142012-04-03 08:46:54 -03003095 if (c->type == SCO_LINK || c->type == ESCO_LINK)
Johan Hedberg4c659c32011-11-07 23:13:39 +02003096 continue;
3097 i++;
3098 }
3099
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02003100 rp->conn_count = cpu_to_le16(i);
Johan Hedberg60fc5fb62012-02-23 09:52:28 +02003101
Johan Hedberg4c659c32011-11-07 23:13:39 +02003102 /* Recalculate length in case of filtered SCO connections, etc */
3103 rp_len = sizeof(*rp) + (i * sizeof(struct mgmt_addr_info));
Johan Hedberg2784eb42011-01-21 13:56:35 +02003104
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003105 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
3106 rp_len);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003107
Johan Hedberga38528f2011-01-22 06:46:43 +02003108 kfree(rp);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003109
3110unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003111 hci_dev_unlock(hdev);
Johan Hedberg2784eb42011-01-21 13:56:35 +02003112 return err;
3113}
3114
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003115static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003116 struct mgmt_cp_pin_code_neg_reply *cp)
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003117{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003118 struct mgmt_pending_cmd *cmd;
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003119 int err;
3120
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003121 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003122 sizeof(*cp));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003123 if (!cmd)
3124 return -ENOMEM;
3125
Johan Hedbergd8457692012-02-17 14:24:57 +02003126 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003127 sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003128 if (err < 0)
3129 mgmt_pending_remove(cmd);
3130
3131 return err;
3132}
3133
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003134static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003135 u16 len)
Johan Hedberg980e1a52011-01-22 06:10:07 +02003136{
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003137 struct hci_conn *conn;
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003138 struct mgmt_cp_pin_code_reply *cp = data;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003139 struct hci_cp_pin_code_reply reply;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003140 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003141 int err;
3142
3143 BT_DBG("");
3144
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003145 hci_dev_lock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003146
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003147 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003148 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3149 MGMT_STATUS_NOT_POWERED);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003150 goto failed;
3151 }
3152
Johan Hedbergd8457692012-02-17 14:24:57 +02003153 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003154 if (!conn) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003155 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3156 MGMT_STATUS_NOT_CONNECTED);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003157 goto failed;
3158 }
3159
3160 if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
Johan Hedbergd8457692012-02-17 14:24:57 +02003161 struct mgmt_cp_pin_code_neg_reply ncp;
3162
3163 memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003164
3165 BT_ERR("PIN code is not 16 bytes long");
3166
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003167 err = send_pin_code_neg_reply(sk, hdev, &ncp);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003168 if (err >= 0)
Johan Hedberga69e8372015-03-06 21:08:53 +02003169 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
3170 MGMT_STATUS_INVALID_PARAMS);
Waldemar Rymarkiewicz96d97a62011-06-01 17:28:48 +02003171
3172 goto failed;
3173 }
3174
Gustavo F. Padovan00abfe42012-03-01 00:37:10 -03003175 cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
Johan Hedberg366a0332011-02-19 12:05:55 -03003176 if (!cmd) {
3177 err = -ENOMEM;
Johan Hedberg980e1a52011-01-22 06:10:07 +02003178 goto failed;
Johan Hedberg366a0332011-02-19 12:05:55 -03003179 }
Johan Hedberg980e1a52011-01-22 06:10:07 +02003180
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003181 cmd->cmd_complete = addr_cmd_complete;
3182
Johan Hedbergd8457692012-02-17 14:24:57 +02003183 bacpy(&reply.bdaddr, &cp->addr.bdaddr);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003184 reply.pin_len = cp->pin_len;
Waldemar Rymarkiewicz24718ca2011-06-01 17:28:47 +02003185 memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
Johan Hedberg980e1a52011-01-22 06:10:07 +02003186
3187 err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
3188 if (err < 0)
Johan Hedberga664b5b2011-02-19 12:06:02 -03003189 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003190
3191failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003192 hci_dev_unlock(hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02003193 return err;
3194}
3195
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003196static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
3197 u16 len)
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003198{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003199 struct mgmt_cp_set_io_capability *cp = data;
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003200
3201 BT_DBG("");
3202
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003203 if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003204 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
3205 MGMT_STATUS_INVALID_PARAMS, NULL, 0);
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003206
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003207 hci_dev_lock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003208
3209 hdev->io_capability = cp->io_capability;
3210
3211 BT_DBG("%s IO capability set to 0x%02x", hdev->name,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003212 hdev->io_capability);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003213
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003214 hci_dev_unlock(hdev);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003215
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003216 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
3217 NULL, 0);
Johan Hedberg17fa4b92011-01-25 13:28:33 +02003218}
3219
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003220static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003221{
3222 struct hci_dev *hdev = conn->hdev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003223 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003224
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003225 list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
Johan Hedberge9a416b2011-02-19 12:05:56 -03003226 if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
3227 continue;
3228
Johan Hedberge9a416b2011-02-19 12:05:56 -03003229 if (cmd->user_data != conn)
3230 continue;
3231
3232 return cmd;
3233 }
3234
3235 return NULL;
3236}
3237
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003238static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003239{
3240 struct mgmt_rp_pair_device rp;
3241 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9df74652014-12-19 22:26:03 +02003242 int err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003243
Johan Hedberg61b1a7f2014-03-20 12:54:16 +02003244 bacpy(&rp.addr.bdaddr, &conn->dst);
3245 rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003246
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003247 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
3248 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003249
3250 /* So we don't get further callbacks for this connection */
3251 conn->connect_cfm_cb = NULL;
3252 conn->security_cfm_cb = NULL;
3253 conn->disconn_cfm_cb = NULL;
3254
David Herrmann76a68ba2013-04-06 20:28:37 +02003255 hci_conn_drop(conn);
Alfonso Acosta89cbb062014-10-11 21:44:47 +00003256
3257 /* The device is paired so there is no need to remove
3258 * its connection parameters anymore.
3259 */
3260 clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
Johan Hedberg15013ae2014-12-11 21:45:44 +02003261
3262 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02003263
3264 return err;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003265}
3266
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003267void mgmt_smp_complete(struct hci_conn *conn, bool complete)
3268{
3269 u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003270 struct mgmt_pending_cmd *cmd;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003271
3272 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003273 if (cmd) {
Johan Hedberg04ab2742014-12-05 13:36:04 +02003274 cmd->cmd_complete(cmd, status);
Johan Hedberga511b352014-12-11 21:45:45 +02003275 mgmt_pending_remove(cmd);
3276 }
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003277}
3278
Johan Hedberge9a416b2011-02-19 12:05:56 -03003279static void pairing_complete_cb(struct hci_conn *conn, u8 status)
3280{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003281 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003282
3283 BT_DBG("status %u", status);
3284
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003285 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003286 if (!cmd) {
Johan Hedberg56e5cb82011-11-08 20:40:16 +02003287 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003288 return;
3289 }
3290
3291 cmd->cmd_complete(cmd, mgmt_status(status));
3292 mgmt_pending_remove(cmd);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003293}
3294
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003295static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303296{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003297 struct mgmt_pending_cmd *cmd;
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303298
3299 BT_DBG("status %u", status);
3300
3301 if (!status)
3302 return;
3303
3304 cmd = find_pairing(conn);
Johan Hedberga511b352014-12-11 21:45:45 +02003305 if (!cmd) {
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303306 BT_DBG("Unable to find a pending command");
Johan Hedberga511b352014-12-11 21:45:45 +02003307 return;
3308 }
3309
3310 cmd->cmd_complete(cmd, mgmt_status(status));
3311 mgmt_pending_remove(cmd);
Vishal Agarwal4c47d732012-06-07 20:27:35 +05303312}
3313
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003314static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003315 u16 len)
Johan Hedberge9a416b2011-02-19 12:05:56 -03003316{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003317 struct mgmt_cp_pair_device *cp = data;
Johan Hedberg1425acb2011-11-11 00:07:35 +02003318 struct mgmt_rp_pair_device rp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003319 struct mgmt_pending_cmd *cmd;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003320 u8 sec_level, auth_type;
3321 struct hci_conn *conn;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003322 int err;
3323
3324 BT_DBG("");
3325
Szymon Jancf950a30e2013-01-18 12:48:07 +01003326 memset(&rp, 0, sizeof(rp));
3327 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
3328 rp.addr.type = cp->addr.type;
3329
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003330 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003331 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3332 MGMT_STATUS_INVALID_PARAMS,
3333 &rp, sizeof(rp));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02003334
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003335 if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003336 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3337 MGMT_STATUS_INVALID_PARAMS,
3338 &rp, sizeof(rp));
Johan Hedberg4ec86d42014-06-17 15:14:48 +03003339
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003340 hci_dev_lock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003341
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003342 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003343 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3344 MGMT_STATUS_NOT_POWERED, &rp,
3345 sizeof(rp));
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003346 goto unlock;
3347 }
3348
Johan Hedberg55e76b32015-03-10 22:34:40 +02003349 if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
3350 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3351 MGMT_STATUS_ALREADY_PAIRED, &rp,
3352 sizeof(rp));
3353 goto unlock;
3354 }
3355
Vinicius Costa Gomesc908df32011-09-02 14:51:22 -03003356 sec_level = BT_SECURITY_MEDIUM;
Mikel Astiz6fd6b912014-04-08 14:21:32 +02003357 auth_type = HCI_AT_DEDICATED_BONDING;
Johan Hedberge9a416b2011-02-19 12:05:56 -03003358
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003359 if (cp->addr.type == BDADDR_BREDR) {
Andre Guedes04a6c582014-02-26 20:21:44 -03003360 conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
3361 auth_type);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003362 } else {
3363 u8 addr_type;
3364
3365 /* Convert from L2CAP channel address type to HCI address type
3366 */
3367 if (cp->addr.type == BDADDR_LE_PUBLIC)
3368 addr_type = ADDR_LE_DEV_PUBLIC;
3369 else
3370 addr_type = ADDR_LE_DEV_RANDOM;
3371
Marcel Holtmann7c264b12014-06-30 12:34:40 +02003372 /* When pairing a new device, it is expected to remember
3373 * this device for future connections. Adding the connection
3374 * parameter information ahead of time allows tracking
3375 * of the slave preferred values and will speed up any
3376 * further connection establishment.
3377 *
3378 * If connection parameters already exist, then they
3379 * will be kept and this function does nothing.
3380 */
3381 hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
3382
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003383 conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type,
Johan Hedberge804d252014-07-16 11:42:28 +03003384 sec_level, HCI_LE_CONN_TIMEOUT,
3385 HCI_ROLE_MASTER);
Andre Guedes6f77d8c2014-02-26 20:21:45 -03003386 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003387
Ville Tervo30e76272011-02-22 16:10:53 -03003388 if (IS_ERR(conn)) {
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003389 int status;
3390
3391 if (PTR_ERR(conn) == -EBUSY)
3392 status = MGMT_STATUS_BUSY;
Lukasz Rymanowskifaa81032015-02-11 12:31:42 +01003393 else if (PTR_ERR(conn) == -EOPNOTSUPP)
3394 status = MGMT_STATUS_NOT_SUPPORTED;
3395 else if (PTR_ERR(conn) == -ECONNREFUSED)
3396 status = MGMT_STATUS_REJECTED;
Andrzej Kaczmarek489dc482012-05-30 15:39:22 +02003397 else
3398 status = MGMT_STATUS_CONNECT_FAILED;
3399
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003400 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3401 status, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003402 goto unlock;
3403 }
3404
3405 if (conn->connect_cfm_cb) {
David Herrmann76a68ba2013-04-06 20:28:37 +02003406 hci_conn_drop(conn);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003407 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
3408 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberge9a416b2011-02-19 12:05:56 -03003409 goto unlock;
3410 }
3411
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003412 cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003413 if (!cmd) {
3414 err = -ENOMEM;
David Herrmann76a68ba2013-04-06 20:28:37 +02003415 hci_conn_drop(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003416 goto unlock;
3417 }
3418
Johan Hedberg04ab2742014-12-05 13:36:04 +02003419 cmd->cmd_complete = pairing_complete;
3420
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003421 /* For LE, just connecting isn't a proof that the pairing finished */
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003422 if (cp->addr.type == BDADDR_BREDR) {
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003423 conn->connect_cfm_cb = pairing_complete_cb;
Johan Hedbergf4a407b2014-02-18 21:41:34 +02003424 conn->security_cfm_cb = pairing_complete_cb;
3425 conn->disconn_cfm_cb = pairing_complete_cb;
3426 } else {
3427 conn->connect_cfm_cb = le_pairing_complete_cb;
3428 conn->security_cfm_cb = le_pairing_complete_cb;
3429 conn->disconn_cfm_cb = le_pairing_complete_cb;
3430 }
Vinicius Costa Gomes7a512d02011-08-19 21:06:54 -03003431
Johan Hedberge9a416b2011-02-19 12:05:56 -03003432 conn->io_capability = cp->io_cap;
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03003433 cmd->user_data = hci_conn_get(conn);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003434
Johan Hedberg6f78fd42014-07-30 08:35:48 +03003435 if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
Johan Hedberga511b352014-12-11 21:45:45 +02003436 hci_conn_security(conn, sec_level, auth_type, true)) {
3437 cmd->cmd_complete(cmd, 0);
3438 mgmt_pending_remove(cmd);
3439 }
Johan Hedberge9a416b2011-02-19 12:05:56 -03003440
3441 err = 0;
3442
3443unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003444 hci_dev_unlock(hdev);
Johan Hedberge9a416b2011-02-19 12:05:56 -03003445 return err;
3446}
3447
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003448static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
3449 u16 len)
Johan Hedberg28424702012-02-02 04:02:29 +02003450{
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003451 struct mgmt_addr_info *addr = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003452 struct mgmt_pending_cmd *cmd;
Johan Hedberg28424702012-02-02 04:02:29 +02003453 struct hci_conn *conn;
3454 int err;
3455
3456 BT_DBG("");
3457
Johan Hedberg28424702012-02-02 04:02:29 +02003458 hci_dev_lock(hdev);
3459
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003460 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003461 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3462 MGMT_STATUS_NOT_POWERED);
Johan Hedberg5f97c1d2012-02-22 22:41:18 +02003463 goto unlock;
3464 }
3465
Johan Hedberg28424702012-02-02 04:02:29 +02003466 cmd = mgmt_pending_find(MGMT_OP_PAIR_DEVICE, hdev);
3467 if (!cmd) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003468 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3469 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003470 goto unlock;
3471 }
3472
3473 conn = cmd->user_data;
3474
3475 if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003476 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
3477 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg28424702012-02-02 04:02:29 +02003478 goto unlock;
3479 }
3480
Johan Hedberga511b352014-12-11 21:45:45 +02003481 cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
3482 mgmt_pending_remove(cmd);
Johan Hedberg28424702012-02-02 04:02:29 +02003483
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003484 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
3485 addr, sizeof(*addr));
Johan Hedberg28424702012-02-02 04:02:29 +02003486unlock:
3487 hci_dev_unlock(hdev);
Johan Hedberg28424702012-02-02 04:02:29 +02003488 return err;
3489}
3490
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003491static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
Johan Hedberg1707c602013-03-15 17:07:15 -05003492 struct mgmt_addr_info *addr, u16 mgmt_op,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003493 u16 hci_op, __le32 passkey)
Johan Hedberga5c29682011-02-19 12:05:57 -03003494{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003495 struct mgmt_pending_cmd *cmd;
Brian Gix0df4c182011-11-16 13:53:13 -08003496 struct hci_conn *conn;
Johan Hedberga5c29682011-02-19 12:05:57 -03003497 int err;
3498
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003499 hci_dev_lock(hdev);
Johan Hedberg08ba5382011-03-16 14:29:34 +02003500
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003501 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003502 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3503 MGMT_STATUS_NOT_POWERED, addr,
3504 sizeof(*addr));
Brian Gix0df4c182011-11-16 13:53:13 -08003505 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003506 }
3507
Johan Hedberg1707c602013-03-15 17:07:15 -05003508 if (addr->type == BDADDR_BREDR)
3509 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
Johan Hedberg272d90d2012-02-09 15:26:12 +02003510 else
Johan Hedberg1707c602013-03-15 17:07:15 -05003511 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &addr->bdaddr);
Brian Gix47c15e22011-11-16 13:53:14 -08003512
Johan Hedberg272d90d2012-02-09 15:26:12 +02003513 if (!conn) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003514 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3515 MGMT_STATUS_NOT_CONNECTED, addr,
3516 sizeof(*addr));
Johan Hedberg272d90d2012-02-09 15:26:12 +02003517 goto done;
3518 }
3519
Johan Hedberg1707c602013-03-15 17:07:15 -05003520 if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
Brian Gix5fe57d92011-12-21 16:12:13 -08003521 err = smp_user_confirm_reply(conn, mgmt_op, passkey);
Brian Gix5fe57d92011-12-21 16:12:13 -08003522 if (!err)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003523 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3524 MGMT_STATUS_SUCCESS, addr,
3525 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003526 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003527 err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
3528 MGMT_STATUS_FAILED, addr,
3529 sizeof(*addr));
Brian Gix5fe57d92011-12-21 16:12:13 -08003530
Brian Gix47c15e22011-11-16 13:53:14 -08003531 goto done;
3532 }
3533
Johan Hedberg1707c602013-03-15 17:07:15 -05003534 cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
Johan Hedberga5c29682011-02-19 12:05:57 -03003535 if (!cmd) {
3536 err = -ENOMEM;
Brian Gix0df4c182011-11-16 13:53:13 -08003537 goto done;
Johan Hedberga5c29682011-02-19 12:05:57 -03003538 }
3539
Johan Hedberg7776d1d2014-12-05 13:36:03 +02003540 cmd->cmd_complete = addr_cmd_complete;
3541
Brian Gix0df4c182011-11-16 13:53:13 -08003542 /* Continue with pairing via HCI */
Brian Gix604086b2011-11-23 08:28:33 -08003543 if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
3544 struct hci_cp_user_passkey_reply cp;
3545
Johan Hedberg1707c602013-03-15 17:07:15 -05003546 bacpy(&cp.bdaddr, &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003547 cp.passkey = passkey;
3548 err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
3549 } else
Johan Hedberg1707c602013-03-15 17:07:15 -05003550 err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
3551 &addr->bdaddr);
Brian Gix604086b2011-11-23 08:28:33 -08003552
Johan Hedberga664b5b2011-02-19 12:06:02 -03003553 if (err < 0)
3554 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03003555
Brian Gix0df4c182011-11-16 13:53:13 -08003556done:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003557 hci_dev_unlock(hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03003558 return err;
3559}
3560
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303561static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
3562 void *data, u16 len)
3563{
3564 struct mgmt_cp_pin_code_neg_reply *cp = data;
3565
3566 BT_DBG("");
3567
Johan Hedberg1707c602013-03-15 17:07:15 -05003568 return user_pairing_resp(sk, hdev, &cp->addr,
Jaganath Kanakkasseryafeb0192012-07-09 16:11:51 +05303569 MGMT_OP_PIN_CODE_NEG_REPLY,
3570 HCI_OP_PIN_CODE_NEG_REPLY, 0);
3571}
3572
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003573static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3574 u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003575{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003576 struct mgmt_cp_user_confirm_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003577
3578 BT_DBG("");
3579
3580 if (len != sizeof(*cp))
Johan Hedberga69e8372015-03-06 21:08:53 +02003581 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
3582 MGMT_STATUS_INVALID_PARAMS);
Brian Gix0df4c182011-11-16 13:53:13 -08003583
Johan Hedberg1707c602013-03-15 17:07:15 -05003584 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003585 MGMT_OP_USER_CONFIRM_REPLY,
3586 HCI_OP_USER_CONFIRM_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003587}
3588
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003589static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003590 void *data, u16 len)
Brian Gix0df4c182011-11-16 13:53:13 -08003591{
Johan Hedbergc9c26592011-12-15 00:47:41 +02003592 struct mgmt_cp_user_confirm_neg_reply *cp = data;
Brian Gix0df4c182011-11-16 13:53:13 -08003593
3594 BT_DBG("");
3595
Johan Hedberg1707c602013-03-15 17:07:15 -05003596 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003597 MGMT_OP_USER_CONFIRM_NEG_REPLY,
3598 HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
Brian Gix0df4c182011-11-16 13:53:13 -08003599}
3600
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003601static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
3602 u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003603{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003604 struct mgmt_cp_user_passkey_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003605
3606 BT_DBG("");
3607
Johan Hedberg1707c602013-03-15 17:07:15 -05003608 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003609 MGMT_OP_USER_PASSKEY_REPLY,
3610 HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
Brian Gix604086b2011-11-23 08:28:33 -08003611}
3612
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003613static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003614 void *data, u16 len)
Brian Gix604086b2011-11-23 08:28:33 -08003615{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003616 struct mgmt_cp_user_passkey_neg_reply *cp = data;
Brian Gix604086b2011-11-23 08:28:33 -08003617
3618 BT_DBG("");
3619
Johan Hedberg1707c602013-03-15 17:07:15 -05003620 return user_pairing_resp(sk, hdev, &cp->addr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003621 MGMT_OP_USER_PASSKEY_NEG_REPLY,
3622 HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
Brian Gix604086b2011-11-23 08:28:33 -08003623}
3624
Johan Hedberg13928972013-03-15 17:07:00 -05003625static void update_name(struct hci_request *req)
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003626{
Johan Hedberg13928972013-03-15 17:07:00 -05003627 struct hci_dev *hdev = req->hdev;
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003628 struct hci_cp_write_local_name cp;
3629
Johan Hedberg13928972013-03-15 17:07:00 -05003630 memcpy(cp.name, hdev->dev_name, sizeof(cp.name));
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003631
Johan Hedberg890ea892013-03-15 17:06:52 -05003632 hci_req_add(req, HCI_OP_WRITE_LOCAL_NAME, sizeof(cp), &cp);
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003633}
3634
Marcel Holtmann1904a852015-01-11 13:50:44 -08003635static void set_name_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg13928972013-03-15 17:07:00 -05003636{
3637 struct mgmt_cp_set_local_name *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003638 struct mgmt_pending_cmd *cmd;
Johan Hedberg13928972013-03-15 17:07:00 -05003639
3640 BT_DBG("status 0x%02x", status);
3641
3642 hci_dev_lock(hdev);
3643
3644 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
3645 if (!cmd)
3646 goto unlock;
3647
3648 cp = cmd->param;
3649
3650 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02003651 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
3652 mgmt_status(status));
Johan Hedberg13928972013-03-15 17:07:00 -05003653 else
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003654 mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3655 cp, sizeof(*cp));
Johan Hedberg13928972013-03-15 17:07:00 -05003656
3657 mgmt_pending_remove(cmd);
3658
3659unlock:
3660 hci_dev_unlock(hdev);
3661}
3662
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003663static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003664 u16 len)
Johan Hedbergb312b1612011-03-16 14:29:37 +02003665{
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003666 struct mgmt_cp_set_local_name *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003667 struct mgmt_pending_cmd *cmd;
Johan Hedberg890ea892013-03-15 17:06:52 -05003668 struct hci_request req;
Johan Hedbergb312b1612011-03-16 14:29:37 +02003669 int err;
3670
3671 BT_DBG("");
3672
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003673 hci_dev_lock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003674
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003675 /* If the old values are the same as the new ones just return a
3676 * direct command complete event.
3677 */
3678 if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
3679 !memcmp(hdev->short_name, cp->short_name,
3680 sizeof(hdev->short_name))) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003681 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3682 data, len);
Johan Hedbergb3f2ca92013-03-15 17:07:03 -05003683 goto failed;
3684 }
3685
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003686 memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003687
Johan Hedbergb5235a62012-02-21 14:32:24 +02003688 if (!hdev_is_powered(hdev)) {
Johan Hedberg2b4bf392012-03-03 00:19:06 +02003689 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003690
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003691 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
3692 data, len);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003693 if (err < 0)
3694 goto failed;
3695
Marcel Holtmannf6b77122015-03-14 19:28:05 -07003696 err = mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev,
3697 data, len, sk);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003698
Johan Hedbergb5235a62012-02-21 14:32:24 +02003699 goto failed;
3700 }
3701
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02003702 cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003703 if (!cmd) {
3704 err = -ENOMEM;
3705 goto failed;
3706 }
3707
Johan Hedberg13928972013-03-15 17:07:00 -05003708 memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
3709
Johan Hedberg890ea892013-03-15 17:06:52 -05003710 hci_req_init(&req, hdev);
Johan Hedberg3f985052013-03-15 17:07:02 -05003711
3712 if (lmp_bredr_capable(hdev)) {
3713 update_name(&req);
3714 update_eir(&req);
3715 }
3716
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003717 /* The name is stored in the scan response data and so
3718 * no need to udpate the advertising data here.
3719 */
Johan Hedberg3f985052013-03-15 17:07:02 -05003720 if (lmp_le_capable(hdev))
Marcel Holtmann7a5f4992013-10-16 00:16:49 -07003721 update_scan_rsp_data(&req);
Johan Hedberg3f985052013-03-15 17:07:02 -05003722
Johan Hedberg13928972013-03-15 17:07:00 -05003723 err = hci_req_run(&req, set_name_complete);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003724 if (err < 0)
3725 mgmt_pending_remove(cmd);
3726
3727failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003728 hci_dev_unlock(hdev);
Johan Hedbergb312b1612011-03-16 14:29:37 +02003729 return err;
3730}
3731
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02003732static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003733 void *data, u16 data_len)
Szymon Jancc35938b2011-03-22 13:12:21 +01003734{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02003735 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01003736 int err;
3737
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003738 BT_DBG("%s", hdev->name);
Szymon Jancc35938b2011-03-22 13:12:21 +01003739
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003740 hci_dev_lock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003741
Johan Hedberg4b34ee782012-02-21 14:13:02 +02003742 if (!hdev_is_powered(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003743 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3744 MGMT_STATUS_NOT_POWERED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003745 goto unlock;
3746 }
3747
Andre Guedes9a1a1992012-07-24 15:03:48 -03003748 if (!lmp_ssp_capable(hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003749 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3750 MGMT_STATUS_NOT_SUPPORTED);
Szymon Jancc35938b2011-03-22 13:12:21 +01003751 goto unlock;
3752 }
3753
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003754 if (mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02003755 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
3756 MGMT_STATUS_BUSY);
Szymon Jancc35938b2011-03-22 13:12:21 +01003757 goto unlock;
3758 }
3759
Johan Hedberg2e58ef32011-11-08 20:40:15 +02003760 cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
Szymon Jancc35938b2011-03-22 13:12:21 +01003761 if (!cmd) {
3762 err = -ENOMEM;
3763 goto unlock;
3764 }
3765
Johan Hedberg710f11c2014-05-26 11:21:22 +03003766 if (bredr_sc_enabled(hdev))
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08003767 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
3768 0, NULL);
3769 else
3770 err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
3771
Szymon Jancc35938b2011-03-22 13:12:21 +01003772 if (err < 0)
3773 mgmt_pending_remove(cmd);
3774
3775unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003776 hci_dev_unlock(hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01003777 return err;
3778}
3779
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003780static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03003781 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003782{
Johan Hedberg5d57e792015-01-23 10:10:38 +02003783 struct mgmt_addr_info *addr = data;
Szymon Janc2763eda2011-03-22 13:12:22 +01003784 int err;
3785
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003786 BT_DBG("%s ", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003787
Johan Hedberg5d57e792015-01-23 10:10:38 +02003788 if (!bdaddr_type_is_valid(addr->type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003789 return mgmt_cmd_complete(sk, hdev->id,
3790 MGMT_OP_ADD_REMOTE_OOB_DATA,
3791 MGMT_STATUS_INVALID_PARAMS,
3792 addr, sizeof(*addr));
Johan Hedberg5d57e792015-01-23 10:10:38 +02003793
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003794 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003795
Marcel Holtmannec109112014-01-10 02:07:30 -08003796 if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
3797 struct mgmt_cp_add_remote_oob_data *cp = data;
3798 u8 status;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003799
Johan Hedbergc19a4952014-11-17 20:52:19 +02003800 if (cp->addr.type != BDADDR_BREDR) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003801 err = mgmt_cmd_complete(sk, hdev->id,
3802 MGMT_OP_ADD_REMOTE_OOB_DATA,
3803 MGMT_STATUS_INVALID_PARAMS,
3804 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003805 goto unlock;
3806 }
3807
Marcel Holtmannec109112014-01-10 02:07:30 -08003808 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg6928a922014-10-26 20:46:09 +01003809 cp->addr.type, cp->hash,
3810 cp->rand, NULL, NULL);
Marcel Holtmannec109112014-01-10 02:07:30 -08003811 if (err < 0)
3812 status = MGMT_STATUS_FAILED;
3813 else
3814 status = MGMT_STATUS_SUCCESS;
3815
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003816 err = mgmt_cmd_complete(sk, hdev->id,
3817 MGMT_OP_ADD_REMOTE_OOB_DATA, status,
3818 &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003819 } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
3820 struct mgmt_cp_add_remote_oob_ext_data *cp = data;
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003821 u8 *rand192, *hash192, *rand256, *hash256;
Marcel Holtmannec109112014-01-10 02:07:30 -08003822 u8 status;
3823
Johan Hedberg86df9202014-10-26 20:52:27 +01003824 if (bdaddr_type_is_le(cp->addr.type)) {
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003825 /* Enforce zero-valued 192-bit parameters as
3826 * long as legacy SMP OOB isn't implemented.
3827 */
3828 if (memcmp(cp->rand192, ZERO_KEY, 16) ||
3829 memcmp(cp->hash192, ZERO_KEY, 16)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003830 err = mgmt_cmd_complete(sk, hdev->id,
3831 MGMT_OP_ADD_REMOTE_OOB_DATA,
3832 MGMT_STATUS_INVALID_PARAMS,
3833 addr, sizeof(*addr));
Johan Hedbergd25b78e2015-01-27 12:55:52 +02003834 goto unlock;
3835 }
3836
Johan Hedberg86df9202014-10-26 20:52:27 +01003837 rand192 = NULL;
3838 hash192 = NULL;
3839 } else {
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003840 /* In case one of the P-192 values is set to zero,
3841 * then just disable OOB data for P-192.
3842 */
3843 if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
3844 !memcmp(cp->hash192, ZERO_KEY, 16)) {
3845 rand192 = NULL;
3846 hash192 = NULL;
3847 } else {
3848 rand192 = cp->rand192;
3849 hash192 = cp->hash192;
3850 }
3851 }
3852
3853 /* In case one of the P-256 values is set to zero, then just
3854 * disable OOB data for P-256.
3855 */
3856 if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
3857 !memcmp(cp->hash256, ZERO_KEY, 16)) {
3858 rand256 = NULL;
3859 hash256 = NULL;
3860 } else {
3861 rand256 = cp->rand256;
3862 hash256 = cp->hash256;
Johan Hedberg86df9202014-10-26 20:52:27 +01003863 }
3864
Johan Hedberg81328d5c2014-10-26 20:33:47 +01003865 err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
Johan Hedberg86df9202014-10-26 20:52:27 +01003866 cp->addr.type, hash192, rand192,
Marcel Holtmann41bcfd52015-01-31 00:37:02 -08003867 hash256, rand256);
Marcel Holtmannec109112014-01-10 02:07:30 -08003868 if (err < 0)
3869 status = MGMT_STATUS_FAILED;
3870 else
3871 status = MGMT_STATUS_SUCCESS;
3872
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003873 err = mgmt_cmd_complete(sk, hdev->id,
3874 MGMT_OP_ADD_REMOTE_OOB_DATA,
3875 status, &cp->addr, sizeof(cp->addr));
Marcel Holtmannec109112014-01-10 02:07:30 -08003876 } else {
3877 BT_ERR("add_remote_oob_data: invalid length of %u bytes", len);
Johan Hedberga69e8372015-03-06 21:08:53 +02003878 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
3879 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannec109112014-01-10 02:07:30 -08003880 }
Szymon Janc2763eda2011-03-22 13:12:22 +01003881
Johan Hedbergc19a4952014-11-17 20:52:19 +02003882unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003883 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003884 return err;
3885}
3886
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003887static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03003888 void *data, u16 len)
Szymon Janc2763eda2011-03-22 13:12:22 +01003889{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03003890 struct mgmt_cp_remove_remote_oob_data *cp = data;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003891 u8 status;
Szymon Janc2763eda2011-03-22 13:12:22 +01003892 int err;
3893
Johan Hedbergbdb6d972012-02-28 06:13:32 +02003894 BT_DBG("%s", hdev->name);
Szymon Janc2763eda2011-03-22 13:12:22 +01003895
Johan Hedbergc19a4952014-11-17 20:52:19 +02003896 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003897 return mgmt_cmd_complete(sk, hdev->id,
3898 MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3899 MGMT_STATUS_INVALID_PARAMS,
3900 &cp->addr, sizeof(cp->addr));
Johan Hedbergc19a4952014-11-17 20:52:19 +02003901
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003902 hci_dev_lock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003903
Johan Hedbergeedbd582014-11-15 09:34:23 +02003904 if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
3905 hci_remote_oob_data_clear(hdev);
3906 status = MGMT_STATUS_SUCCESS;
3907 goto done;
3908 }
3909
Johan Hedberg6928a922014-10-26 20:46:09 +01003910 err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
Szymon Janc2763eda2011-03-22 13:12:22 +01003911 if (err < 0)
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003912 status = MGMT_STATUS_INVALID_PARAMS;
Szymon Janc2763eda2011-03-22 13:12:22 +01003913 else
Szymon Janca6785be2012-12-13 15:11:21 +01003914 status = MGMT_STATUS_SUCCESS;
Johan Hedbergbf1e3542012-02-19 13:16:14 +02003915
Johan Hedbergeedbd582014-11-15 09:34:23 +02003916done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02003917 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
3918 status, &cp->addr, sizeof(cp->addr));
Szymon Janc2763eda2011-03-22 13:12:22 +01003919
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03003920 hci_dev_unlock(hdev);
Szymon Janc2763eda2011-03-22 13:12:22 +01003921 return err;
3922}
3923
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003924static bool trigger_bredr_inquiry(struct hci_request *req, u8 *status)
3925{
3926 struct hci_dev *hdev = req->hdev;
3927 struct hci_cp_inquiry cp;
3928 /* General inquiry access code (GIAC) */
3929 u8 lap[3] = { 0x33, 0x8b, 0x9e };
3930
3931 *status = mgmt_bredr_support(hdev);
3932 if (*status)
3933 return false;
3934
3935 if (hci_dev_test_flag(hdev, HCI_INQUIRY)) {
3936 *status = MGMT_STATUS_BUSY;
3937 return false;
3938 }
3939
3940 hci_inquiry_cache_flush(hdev);
3941
3942 memset(&cp, 0, sizeof(cp));
3943 memcpy(&cp.lap, lap, sizeof(cp.lap));
3944 cp.length = DISCOV_BREDR_INQUIRY_LEN;
3945
3946 hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp);
3947
3948 return true;
3949}
3950
3951static bool trigger_le_scan(struct hci_request *req, u16 interval, u8 *status)
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003952{
Marcel Holtmann80190442014-12-04 11:36:36 +01003953 struct hci_dev *hdev = req->hdev;
3954 struct hci_cp_le_set_scan_param param_cp;
3955 struct hci_cp_le_set_scan_enable enable_cp;
Marcel Holtmann80190442014-12-04 11:36:36 +01003956 u8 own_addr_type;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003957 int err;
3958
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003959 *status = mgmt_le_support(hdev);
3960 if (*status)
3961 return false;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003962
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003963 if (hci_dev_test_flag(hdev, HCI_LE_ADV)) {
3964 /* Don't let discovery abort an outgoing connection attempt
3965 * that's using directed advertising.
3966 */
3967 if (hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) {
3968 *status = MGMT_STATUS_REJECTED;
Marcel Holtmann80190442014-12-04 11:36:36 +01003969 return false;
3970 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003971
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003972 disable_advertising(req);
3973 }
Andre Guedes41dc2bd2013-04-30 15:29:30 -03003974
Jakub Pawlowski812abb12015-03-17 09:04:13 -07003975 /* If controller is scanning, it means the background scanning is
3976 * running. Thus, we should temporarily stop it in order to set the
3977 * discovery scanning parameters.
3978 */
3979 if (hci_dev_test_flag(hdev, HCI_LE_SCAN))
3980 hci_req_add_le_scan_disable(req);
3981
3982 /* All active scans will be done with either a resolvable private
3983 * address (when privacy feature has been enabled) or non-resolvable
3984 * private address.
3985 */
3986 err = hci_update_random_address(req, true, &own_addr_type);
3987 if (err < 0) {
3988 *status = MGMT_STATUS_FAILED;
3989 return false;
3990 }
3991
3992 memset(&param_cp, 0, sizeof(param_cp));
3993 param_cp.type = LE_SCAN_ACTIVE;
3994 param_cp.interval = cpu_to_le16(interval);
3995 param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
3996 param_cp.own_address_type = own_addr_type;
3997
3998 hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
3999 &param_cp);
4000
4001 memset(&enable_cp, 0, sizeof(enable_cp));
4002 enable_cp.enable = LE_SCAN_ENABLE;
4003 enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
4004
4005 hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
4006 &enable_cp);
4007
4008 return true;
4009}
4010
4011static bool trigger_discovery(struct hci_request *req, u8 *status)
4012{
4013 struct hci_dev *hdev = req->hdev;
4014
4015 switch (hdev->discovery.type) {
4016 case DISCOV_TYPE_BREDR:
4017 if (!trigger_bredr_inquiry(req, status))
4018 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004019 break;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004020
Marcel Holtmann80190442014-12-04 11:36:36 +01004021 case DISCOV_TYPE_INTERLEAVED:
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004022 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmann80190442014-12-04 11:36:36 +01004023 *status = MGMT_STATUS_NOT_SUPPORTED;
4024 return false;
4025 }
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004026 /* fall through */
Marcel Holtmann80190442014-12-04 11:36:36 +01004027
Jakub Pawlowski812abb12015-03-17 09:04:13 -07004028 case DISCOV_TYPE_LE:
4029 if (!trigger_le_scan(req, DISCOV_LE_SCAN_INT, status))
Marcel Holtmann80190442014-12-04 11:36:36 +01004030 return false;
Marcel Holtmann80190442014-12-04 11:36:36 +01004031 break;
4032
4033 default:
4034 *status = MGMT_STATUS_INVALID_PARAMS;
4035 return false;
4036 }
4037
4038 return true;
Andre Guedes41dc2bd2013-04-30 15:29:30 -03004039}
4040
Marcel Holtmann1904a852015-01-11 13:50:44 -08004041static void start_discovery_complete(struct hci_dev *hdev, u8 status,
4042 u16 opcode)
Andre Guedes7c307722013-04-30 15:29:28 -03004043{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004044 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004045 unsigned long timeout;
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004046
Andre Guedes7c307722013-04-30 15:29:28 -03004047 BT_DBG("status %d", status);
4048
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004049 hci_dev_lock(hdev);
4050
4051 cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004052 if (!cmd)
4053 cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
4054
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004055 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004056 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004057 mgmt_pending_remove(cmd);
Andre Guedes7c307722013-04-30 15:29:28 -03004058 }
4059
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004060 if (status) {
4061 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4062 goto unlock;
4063 }
4064
Andre Guedes7c307722013-04-30 15:29:28 -03004065 hci_discovery_set_state(hdev, DISCOVERY_FINDING);
Andre Guedes7c307722013-04-30 15:29:28 -03004066
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004067 /* If the scan involves LE scan, pick proper timeout to schedule
4068 * hdev->le_scan_disable that will stop it.
4069 */
Andre Guedes7c307722013-04-30 15:29:28 -03004070 switch (hdev->discovery.type) {
4071 case DISCOV_TYPE_LE:
Lukasz Rymanowski3d5a76f2014-03-27 20:55:21 +01004072 timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
Andre Guedes7c307722013-04-30 15:29:28 -03004073 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004074 case DISCOV_TYPE_INTERLEAVED:
Lukasz Rymanowskib9a7a612014-03-27 20:55:20 +01004075 timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
Andre Guedes7c307722013-04-30 15:29:28 -03004076 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004077 case DISCOV_TYPE_BREDR:
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004078 timeout = 0;
Andre Guedes7c307722013-04-30 15:29:28 -03004079 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004080 default:
4081 BT_ERR("Invalid discovery type %d", hdev->discovery.type);
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004082 timeout = 0;
4083 break;
Andre Guedes7c307722013-04-30 15:29:28 -03004084 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004085
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004086 if (timeout) {
4087 /* When service discovery is used and the controller has
4088 * a strict duplicate filter, it is important to remember
4089 * the start and duration of the scan. This is required
4090 * for restarting scanning during the discovery phase.
4091 */
4092 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER,
4093 &hdev->quirks) &&
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004094 hdev->discovery.result_filtering) {
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004095 hdev->discovery.scan_start = jiffies;
4096 hdev->discovery.scan_duration = timeout;
4097 }
4098
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004099 queue_delayed_work(hdev->workqueue,
4100 &hdev->le_scan_disable, timeout);
Jakub Pawlowski2d28cfe2015-02-01 23:07:54 -08004101 }
Lukasz Rymanowskiae55f592014-03-27 20:55:19 +01004102
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004103unlock:
4104 hci_dev_unlock(hdev);
Andre Guedes7c307722013-04-30 15:29:28 -03004105}
4106
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004107static int start_discovery(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004108 void *data, u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004109{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004110 struct mgmt_cp_start_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004111 struct mgmt_pending_cmd *cmd;
Andre Guedes7c307722013-04-30 15:29:28 -03004112 struct hci_request req;
Marcel Holtmann80190442014-12-04 11:36:36 +01004113 u8 status;
Johan Hedberg14a53662011-04-27 10:29:56 -04004114 int err;
4115
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004116 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004117
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004118 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004119
Johan Hedberg4b34ee782012-02-21 14:13:02 +02004120 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004121 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4122 MGMT_STATUS_NOT_POWERED,
4123 &cp->type, sizeof(cp->type));
Johan Hedbergbd2d1332011-11-07 23:13:37 +02004124 goto failed;
4125 }
4126
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004127 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004128 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004129 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4130 MGMT_STATUS_BUSY, &cp->type,
4131 sizeof(cp->type));
Andre Guedes642be6c2012-03-21 00:03:37 -03004132 goto failed;
4133 }
4134
Johan Hedberg2922a942014-12-05 13:36:06 +02004135 cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004136 if (!cmd) {
4137 err = -ENOMEM;
4138 goto failed;
4139 }
4140
Johan Hedberg2922a942014-12-05 13:36:06 +02004141 cmd->cmd_complete = generic_cmd_complete;
4142
Marcel Holtmann22078802014-12-05 11:45:22 +01004143 /* Clear the discovery filter first to free any previously
4144 * allocated memory for the UUID list.
4145 */
4146 hci_discovery_filter_clear(hdev);
4147
Andre Guedes4aab14e2012-02-17 20:39:36 -03004148 hdev->discovery.type = cp->type;
Marcel Holtmannda25cf62014-12-05 13:03:35 +01004149 hdev->discovery.report_invalid_rssi = false;
Andre Guedes4aab14e2012-02-17 20:39:36 -03004150
Andre Guedes7c307722013-04-30 15:29:28 -03004151 hci_req_init(&req, hdev);
4152
Marcel Holtmann80190442014-12-04 11:36:36 +01004153 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004154 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
4155 status, &cp->type, sizeof(cp->type));
Johan Hedberg04106752013-01-10 14:54:09 +02004156 mgmt_pending_remove(cmd);
4157 goto failed;
Andre Guedesf39799f2012-02-17 20:39:35 -03004158 }
Andre Guedes3fd24152012-02-03 17:48:01 -03004159
Andre Guedes7c307722013-04-30 15:29:28 -03004160 err = hci_req_run(&req, start_discovery_complete);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004161 if (err < 0) {
Johan Hedberg14a53662011-04-27 10:29:56 -04004162 mgmt_pending_remove(cmd);
Marcel Holtmannf5a969f2014-12-04 11:36:34 +01004163 goto failed;
4164 }
4165
4166 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
Johan Hedberg14a53662011-04-27 10:29:56 -04004167
4168failed:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004169 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004170 return err;
4171}
4172
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004173static int service_discovery_cmd_complete(struct mgmt_pending_cmd *cmd,
4174 u8 status)
Andre Guedes1183fdc2013-04-30 15:29:35 -03004175{
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004176 return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
4177 cmd->param, 1);
Johan Hedberg2922a942014-12-05 13:36:06 +02004178}
4179
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004180static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
4181 void *data, u16 len)
4182{
4183 struct mgmt_cp_start_service_discovery *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004184 struct mgmt_pending_cmd *cmd;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004185 struct hci_request req;
4186 const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
4187 u16 uuid_count, expected_len;
4188 u8 status;
Andre Guedes1183fdc2013-04-30 15:29:35 -03004189 int err;
4190
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004191 BT_DBG("%s", hdev->name);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004192
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004193 hci_dev_lock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004194
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004195 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004196 err = mgmt_cmd_complete(sk, hdev->id,
4197 MGMT_OP_START_SERVICE_DISCOVERY,
4198 MGMT_STATUS_NOT_POWERED,
4199 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004200 goto failed;
4201 }
4202
4203 if (hdev->discovery.state != DISCOVERY_STOPPED ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004204 hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004205 err = mgmt_cmd_complete(sk, hdev->id,
4206 MGMT_OP_START_SERVICE_DISCOVERY,
4207 MGMT_STATUS_BUSY, &cp->type,
4208 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004209 goto failed;
4210 }
4211
4212 uuid_count = __le16_to_cpu(cp->uuid_count);
4213 if (uuid_count > max_uuid_count) {
4214 BT_ERR("service_discovery: too big uuid_count value %u",
4215 uuid_count);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004216 err = mgmt_cmd_complete(sk, hdev->id,
4217 MGMT_OP_START_SERVICE_DISCOVERY,
4218 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4219 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004220 goto failed;
4221 }
4222
4223 expected_len = sizeof(*cp) + uuid_count * 16;
4224 if (expected_len != len) {
4225 BT_ERR("service_discovery: expected %u bytes, got %u bytes",
4226 expected_len, len);
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004227 err = mgmt_cmd_complete(sk, hdev->id,
4228 MGMT_OP_START_SERVICE_DISCOVERY,
4229 MGMT_STATUS_INVALID_PARAMS, &cp->type,
4230 sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004231 goto failed;
4232 }
4233
4234 cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
Johan Hedberg2922a942014-12-05 13:36:06 +02004235 hdev, data, len);
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004236 if (!cmd) {
4237 err = -ENOMEM;
4238 goto failed;
4239 }
4240
Johan Hedberg2922a942014-12-05 13:36:06 +02004241 cmd->cmd_complete = service_discovery_cmd_complete;
4242
Marcel Holtmann22078802014-12-05 11:45:22 +01004243 /* Clear the discovery filter first to free any previously
4244 * allocated memory for the UUID list.
4245 */
4246 hci_discovery_filter_clear(hdev);
4247
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08004248 hdev->discovery.result_filtering = true;
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004249 hdev->discovery.type = cp->type;
4250 hdev->discovery.rssi = cp->rssi;
4251 hdev->discovery.uuid_count = uuid_count;
4252
4253 if (uuid_count > 0) {
4254 hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
4255 GFP_KERNEL);
4256 if (!hdev->discovery.uuids) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004257 err = mgmt_cmd_complete(sk, hdev->id,
4258 MGMT_OP_START_SERVICE_DISCOVERY,
4259 MGMT_STATUS_FAILED,
4260 &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004261 mgmt_pending_remove(cmd);
4262 goto failed;
4263 }
4264 }
4265
4266 hci_req_init(&req, hdev);
4267
4268 if (!trigger_discovery(&req, &status)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004269 err = mgmt_cmd_complete(sk, hdev->id,
4270 MGMT_OP_START_SERVICE_DISCOVERY,
4271 status, &cp->type, sizeof(cp->type));
Jakub Pawlowski66ea9422014-12-05 10:55:59 +01004272 mgmt_pending_remove(cmd);
4273 goto failed;
4274 }
4275
4276 err = hci_req_run(&req, start_discovery_complete);
4277 if (err < 0) {
4278 mgmt_pending_remove(cmd);
4279 goto failed;
4280 }
4281
4282 hci_discovery_set_state(hdev, DISCOVERY_STARTING);
4283
4284failed:
4285 hci_dev_unlock(hdev);
Andre Guedes1183fdc2013-04-30 15:29:35 -03004286 return err;
4287}
4288
Marcel Holtmann1904a852015-01-11 13:50:44 -08004289static void stop_discovery_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Andre Guedes0e05bba2013-04-30 15:29:33 -03004290{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004291 struct mgmt_pending_cmd *cmd;
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004292
Andre Guedes0e05bba2013-04-30 15:29:33 -03004293 BT_DBG("status %d", status);
4294
4295 hci_dev_lock(hdev);
4296
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004297 cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
4298 if (cmd) {
Johan Hedberg2922a942014-12-05 13:36:06 +02004299 cmd->cmd_complete(cmd, mgmt_status(status));
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004300 mgmt_pending_remove(cmd);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004301 }
4302
Marcel Holtmann11e6e252014-12-04 11:36:35 +01004303 if (!status)
4304 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004305
Andre Guedes0e05bba2013-04-30 15:29:33 -03004306 hci_dev_unlock(hdev);
4307}
4308
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004309static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004310 u16 len)
Johan Hedberg14a53662011-04-27 10:29:56 -04004311{
Johan Hedbergd9306502012-02-20 23:25:18 +02004312 struct mgmt_cp_stop_discovery *mgmt_cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004313 struct mgmt_pending_cmd *cmd;
Andre Guedes0e05bba2013-04-30 15:29:33 -03004314 struct hci_request req;
Johan Hedberg14a53662011-04-27 10:29:56 -04004315 int err;
4316
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004317 BT_DBG("%s", hdev->name);
Johan Hedberg14a53662011-04-27 10:29:56 -04004318
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004319 hci_dev_lock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004320
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004321 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004322 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4323 MGMT_STATUS_REJECTED, &mgmt_cp->type,
4324 sizeof(mgmt_cp->type));
Johan Hedbergd9306502012-02-20 23:25:18 +02004325 goto unlock;
4326 }
4327
4328 if (hdev->discovery.type != mgmt_cp->type) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004329 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
4330 MGMT_STATUS_INVALID_PARAMS,
4331 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004332 goto unlock;
Johan Hedbergff9ef572012-01-04 14:23:45 +02004333 }
4334
Johan Hedberg2922a942014-12-05 13:36:06 +02004335 cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
Johan Hedberg14a53662011-04-27 10:29:56 -04004336 if (!cmd) {
4337 err = -ENOMEM;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004338 goto unlock;
Johan Hedberg14a53662011-04-27 10:29:56 -04004339 }
4340
Johan Hedberg2922a942014-12-05 13:36:06 +02004341 cmd->cmd_complete = generic_cmd_complete;
4342
Andre Guedes0e05bba2013-04-30 15:29:33 -03004343 hci_req_init(&req, hdev);
4344
Johan Hedberg21a60d32014-06-10 14:05:58 +03004345 hci_stop_discovery(&req);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004346
Johan Hedberg21a60d32014-06-10 14:05:58 +03004347 err = hci_req_run(&req, stop_discovery_complete);
4348 if (!err) {
4349 hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
Andre Guedes0e05bba2013-04-30 15:29:33 -03004350 goto unlock;
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004351 }
4352
Johan Hedberg21a60d32014-06-10 14:05:58 +03004353 mgmt_pending_remove(cmd);
4354
4355 /* If no HCI commands were sent we're done */
4356 if (err == -ENODATA) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004357 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY, 0,
4358 &mgmt_cp->type, sizeof(mgmt_cp->type));
Johan Hedberg21a60d32014-06-10 14:05:58 +03004359 hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
4360 }
Johan Hedberg14a53662011-04-27 10:29:56 -04004361
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004362unlock:
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004363 hci_dev_unlock(hdev);
Johan Hedberg14a53662011-04-27 10:29:56 -04004364 return err;
4365}
4366
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004367static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004368 u16 len)
Johan Hedberg561aafb2012-01-04 13:31:59 +02004369{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004370 struct mgmt_cp_confirm_name *cp = data;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004371 struct inquiry_entry *e;
Johan Hedberg561aafb2012-01-04 13:31:59 +02004372 int err;
4373
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004374 BT_DBG("%s", hdev->name);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004375
Johan Hedberg561aafb2012-01-04 13:31:59 +02004376 hci_dev_lock(hdev);
4377
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004378 if (!hci_discovery_active(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004379 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4380 MGMT_STATUS_FAILED, &cp->addr,
4381 sizeof(cp->addr));
Johan Hedberg30dc78e2012-01-04 15:44:20 +02004382 goto failed;
4383 }
4384
Johan Hedberga198e7b2012-02-17 14:27:06 +02004385 e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004386 if (!e) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004387 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
4388 MGMT_STATUS_INVALID_PARAMS, &cp->addr,
4389 sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004390 goto failed;
4391 }
4392
4393 if (cp->name_known) {
4394 e->name_state = NAME_KNOWN;
4395 list_del(&e->list);
4396 } else {
4397 e->name_state = NAME_NEEDED;
Johan Hedberga3d4e202012-01-09 00:53:02 +02004398 hci_inquiry_cache_update_resolve(hdev, e);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004399 }
4400
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004401 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
4402 &cp->addr, sizeof(cp->addr));
Johan Hedberg561aafb2012-01-04 13:31:59 +02004403
4404failed:
4405 hci_dev_unlock(hdev);
Johan Hedberg561aafb2012-01-04 13:31:59 +02004406 return err;
4407}
4408
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004409static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004410 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004411{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004412 struct mgmt_cp_block_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004413 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004414 int err;
4415
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004416 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004417
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004418 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004419 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
4420 MGMT_STATUS_INVALID_PARAMS,
4421 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004422
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004423 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004424
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004425 err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr,
4426 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004427 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004428 status = MGMT_STATUS_FAILED;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004429 goto done;
4430 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004431
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004432 mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4433 sk);
4434 status = MGMT_STATUS_SUCCESS;
4435
4436done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004437 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
4438 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004439
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004440 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004441
4442 return err;
4443}
4444
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004445static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004446 u16 len)
Antti Julku7fbec222011-06-15 12:01:15 +03004447{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004448 struct mgmt_cp_unblock_device *cp = data;
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004449 u8 status;
Antti Julku7fbec222011-06-15 12:01:15 +03004450 int err;
4451
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004452 BT_DBG("%s", hdev->name);
Antti Julku7fbec222011-06-15 12:01:15 +03004453
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004454 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004455 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
4456 MGMT_STATUS_INVALID_PARAMS,
4457 &cp->addr, sizeof(cp->addr));
Johan Hedberg4ee71b22013-01-20 14:27:19 +02004458
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004459 hci_dev_lock(hdev);
Antti Julku5e762442011-08-25 16:48:02 +03004460
Johan Hedbergdcc36c12014-07-09 12:59:13 +03004461 err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr,
4462 cp->addr.type);
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004463 if (err < 0) {
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004464 status = MGMT_STATUS_INVALID_PARAMS;
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004465 goto done;
4466 }
Johan Hedbergf0eeea82012-02-19 12:58:54 +02004467
Johan Hedberg2a8357f2014-07-01 22:09:47 +03004468 mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
4469 sk);
4470 status = MGMT_STATUS_SUCCESS;
4471
4472done:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004473 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
4474 &cp->addr, sizeof(cp->addr));
Antti Julku5e762442011-08-25 16:48:02 +03004475
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -03004476 hci_dev_unlock(hdev);
Antti Julku7fbec222011-06-15 12:01:15 +03004477
4478 return err;
4479}
4480
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004481static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
4482 u16 len)
4483{
4484 struct mgmt_cp_set_device_id *cp = data;
Johan Hedberg890ea892013-03-15 17:06:52 -05004485 struct hci_request req;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004486 int err;
Szymon Jancc72d4b82012-03-16 16:02:57 +01004487 __u16 source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004488
4489 BT_DBG("%s", hdev->name);
4490
Szymon Jancc72d4b82012-03-16 16:02:57 +01004491 source = __le16_to_cpu(cp->source);
4492
4493 if (source > 0x0002)
Johan Hedberga69e8372015-03-06 21:08:53 +02004494 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
4495 MGMT_STATUS_INVALID_PARAMS);
Szymon Jancc72d4b82012-03-16 16:02:57 +01004496
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004497 hci_dev_lock(hdev);
4498
Szymon Jancc72d4b82012-03-16 16:02:57 +01004499 hdev->devid_source = source;
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004500 hdev->devid_vendor = __le16_to_cpu(cp->vendor);
4501 hdev->devid_product = __le16_to_cpu(cp->product);
4502 hdev->devid_version = __le16_to_cpu(cp->version);
4503
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004504 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
4505 NULL, 0);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004506
Johan Hedberg890ea892013-03-15 17:06:52 -05004507 hci_req_init(&req, hdev);
4508 update_eir(&req);
4509 hci_req_run(&req, NULL);
Marcel Holtmanncdbaccc2012-03-11 20:00:29 -07004510
4511 hci_dev_unlock(hdev);
4512
4513 return err;
4514}
4515
Marcel Holtmann1904a852015-01-11 13:50:44 -08004516static void set_advertising_complete(struct hci_dev *hdev, u8 status,
4517 u16 opcode)
Johan Hedberg4375f102013-09-25 13:26:10 +03004518{
4519 struct cmd_lookup match = { NULL, hdev };
4520
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304521 hci_dev_lock(hdev);
4522
Johan Hedberg4375f102013-09-25 13:26:10 +03004523 if (status) {
4524 u8 mgmt_err = mgmt_status(status);
4525
4526 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
4527 cmd_status_rsp, &mgmt_err);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304528 goto unlock;
Johan Hedberg4375f102013-09-25 13:26:10 +03004529 }
4530
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004531 if (hci_dev_test_flag(hdev, HCI_LE_ADV))
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004532 hci_dev_set_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004533 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004534 hci_dev_clear_flag(hdev, HCI_ADVERTISING);
Johan Hedbergc93bd152014-07-08 15:07:48 +03004535
Johan Hedberg4375f102013-09-25 13:26:10 +03004536 mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
4537 &match);
4538
4539 new_settings(hdev, match.sk);
4540
4541 if (match.sk)
4542 sock_put(match.sk);
Jaganath Kanakkassery3ad67582014-12-11 11:43:12 +05304543
4544unlock:
4545 hci_dev_unlock(hdev);
Johan Hedberg4375f102013-09-25 13:26:10 +03004546}
4547
Marcel Holtmann21b51872013-10-10 09:47:53 -07004548static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
4549 u16 len)
Johan Hedberg4375f102013-09-25 13:26:10 +03004550{
4551 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004552 struct mgmt_pending_cmd *cmd;
Johan Hedberg4375f102013-09-25 13:26:10 +03004553 struct hci_request req;
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004554 u8 val, status;
Johan Hedberg4375f102013-09-25 13:26:10 +03004555 int err;
4556
4557 BT_DBG("request for %s", hdev->name);
4558
Johan Hedberge6fe7982013-10-02 15:45:22 +03004559 status = mgmt_le_support(hdev);
4560 if (status)
Johan Hedberga69e8372015-03-06 21:08:53 +02004561 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4562 status);
Johan Hedberg4375f102013-09-25 13:26:10 +03004563
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004564 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02004565 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4566 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg4375f102013-09-25 13:26:10 +03004567
4568 hci_dev_lock(hdev);
4569
4570 val = !!cp->val;
Johan Hedberg4375f102013-09-25 13:26:10 +03004571
Johan Hedbergf74ca9b2013-10-08 15:52:18 +02004572 /* The following conditions are ones which mean that we should
4573 * not do any HCI communication but directly send a mgmt
4574 * response to user space (after toggling the flag if
4575 * necessary).
4576 */
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004577 if (!hdev_is_powered(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004578 (val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
4579 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004580 hci_conn_num(hdev, LE_LINK) > 0 ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004581 (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Johan Hedberge8bb6b92014-07-08 15:07:53 +03004582 hdev->le_scan_type == LE_SCAN_ACTIVE)) {
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004583 bool changed;
Johan Hedberg4375f102013-09-25 13:26:10 +03004584
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004585 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07004586 changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004587 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004588 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004589 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004590 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004591 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07004592 changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004593 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Johan Hedberg4375f102013-09-25 13:26:10 +03004594 }
4595
4596 err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
4597 if (err < 0)
4598 goto unlock;
4599
4600 if (changed)
4601 err = new_settings(hdev, sk);
4602
4603 goto unlock;
4604 }
4605
4606 if (mgmt_pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
4607 mgmt_pending_find(MGMT_OP_SET_LE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004608 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
4609 MGMT_STATUS_BUSY);
Johan Hedberg4375f102013-09-25 13:26:10 +03004610 goto unlock;
4611 }
4612
4613 cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
4614 if (!cmd) {
4615 err = -ENOMEM;
4616 goto unlock;
4617 }
4618
4619 hci_req_init(&req, hdev);
4620
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004621 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004622 hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004623 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004624 hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
Marcel Holtmanncc91cb02015-03-12 22:30:58 -07004625
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07004626 if (val)
4627 enable_advertising(&req);
4628 else
4629 disable_advertising(&req);
Johan Hedberg4375f102013-09-25 13:26:10 +03004630
4631 err = hci_req_run(&req, set_advertising_complete);
4632 if (err < 0)
4633 mgmt_pending_remove(cmd);
4634
4635unlock:
4636 hci_dev_unlock(hdev);
4637 return err;
4638}
4639
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004640static int set_static_address(struct sock *sk, struct hci_dev *hdev,
4641 void *data, u16 len)
4642{
4643 struct mgmt_cp_set_static_address *cp = data;
4644 int err;
4645
4646 BT_DBG("%s", hdev->name);
4647
Marcel Holtmann62af4442013-10-02 22:10:32 -07004648 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004649 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4650 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004651
4652 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004653 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
4654 MGMT_STATUS_REJECTED);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004655
4656 if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
4657 if (!bacmp(&cp->bdaddr, BDADDR_NONE))
Johan Hedberga69e8372015-03-06 21:08:53 +02004658 return mgmt_cmd_status(sk, hdev->id,
4659 MGMT_OP_SET_STATIC_ADDRESS,
4660 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004661
4662 /* Two most significant bits shall be set */
4663 if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
Johan Hedberga69e8372015-03-06 21:08:53 +02004664 return mgmt_cmd_status(sk, hdev->id,
4665 MGMT_OP_SET_STATIC_ADDRESS,
4666 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004667 }
4668
4669 hci_dev_lock(hdev);
4670
4671 bacpy(&hdev->static_addr, &cp->bdaddr);
4672
Marcel Holtmann93690c22015-03-06 10:11:21 -08004673 err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
4674 if (err < 0)
4675 goto unlock;
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004676
Marcel Holtmann93690c22015-03-06 10:11:21 -08004677 err = new_settings(hdev, sk);
4678
4679unlock:
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004680 hci_dev_unlock(hdev);
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07004681 return err;
4682}
4683
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004684static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
4685 void *data, u16 len)
4686{
4687 struct mgmt_cp_set_scan_params *cp = data;
4688 __u16 interval, window;
4689 int err;
4690
4691 BT_DBG("%s", hdev->name);
4692
4693 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004694 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4695 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004696
4697 interval = __le16_to_cpu(cp->interval);
4698
4699 if (interval < 0x0004 || interval > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004700 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4701 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004702
4703 window = __le16_to_cpu(cp->window);
4704
4705 if (window < 0x0004 || window > 0x4000)
Johan Hedberga69e8372015-03-06 21:08:53 +02004706 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4707 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004708
Marcel Holtmann899e1072013-10-14 09:55:32 -07004709 if (window > interval)
Johan Hedberga69e8372015-03-06 21:08:53 +02004710 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
4711 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann899e1072013-10-14 09:55:32 -07004712
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004713 hci_dev_lock(hdev);
4714
4715 hdev->le_scan_interval = interval;
4716 hdev->le_scan_window = window;
4717
Johan Hedberg2a1afb52015-03-06 21:08:54 +02004718 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
4719 NULL, 0);
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004720
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004721 /* If background scan is running, restart it so new parameters are
4722 * loaded.
4723 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004724 if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
Andre Guedesdd2ef8e2014-02-26 20:21:56 -03004725 hdev->discovery.state == DISCOVERY_STOPPED) {
4726 struct hci_request req;
4727
4728 hci_req_init(&req, hdev);
4729
4730 hci_req_add_le_scan_disable(&req);
4731 hci_req_add_le_passive_scan(&req);
4732
4733 hci_req_run(&req, NULL);
4734 }
4735
Marcel Holtmann14b49b92013-10-11 08:23:20 -07004736 hci_dev_unlock(hdev);
4737
4738 return err;
4739}
4740
Marcel Holtmann1904a852015-01-11 13:50:44 -08004741static void fast_connectable_complete(struct hci_dev *hdev, u8 status,
4742 u16 opcode)
Johan Hedberg33e38b32013-03-15 17:07:05 -05004743{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004744 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004745
4746 BT_DBG("status 0x%02x", status);
4747
4748 hci_dev_lock(hdev);
4749
4750 cmd = mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4751 if (!cmd)
4752 goto unlock;
4753
4754 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004755 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4756 mgmt_status(status));
Johan Hedberg33e38b32013-03-15 17:07:05 -05004757 } else {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004758 struct mgmt_mode *cp = cmd->param;
4759
4760 if (cp->val)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004761 hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004762 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004763 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004764
Johan Hedberg33e38b32013-03-15 17:07:05 -05004765 send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
4766 new_settings(hdev, cmd->sk);
4767 }
4768
4769 mgmt_pending_remove(cmd);
4770
4771unlock:
4772 hci_dev_unlock(hdev);
4773}
4774
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004775static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03004776 void *data, u16 len)
Antti Julkuf6422ec2011-06-22 13:11:56 +03004777{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03004778 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004779 struct mgmt_pending_cmd *cmd;
Johan Hedberg33e38b32013-03-15 17:07:05 -05004780 struct hci_request req;
Antti Julkuf6422ec2011-06-22 13:11:56 +03004781 int err;
4782
Johan Hedbergbdb6d972012-02-28 06:13:32 +02004783 BT_DBG("%s", hdev->name);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004784
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004785 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
Johan Hedberg56f87902013-10-02 13:43:13 +03004786 hdev->hci_ver < BLUETOOTH_VER_1_2)
Johan Hedberga69e8372015-03-06 21:08:53 +02004787 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4788 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg33c525c2012-10-24 21:11:58 +03004789
Johan Hedberga7e80f22013-01-09 16:05:19 +02004790 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004791 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4792 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga7e80f22013-01-09 16:05:19 +02004793
Antti Julkuf6422ec2011-06-22 13:11:56 +03004794 hci_dev_lock(hdev);
4795
Johan Hedberg05cbf292013-03-15 17:07:07 -05004796 if (mgmt_pending_find(MGMT_OP_SET_FAST_CONNECTABLE, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004797 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4798 MGMT_STATUS_BUSY);
Johan Hedberg05cbf292013-03-15 17:07:07 -05004799 goto unlock;
4800 }
4801
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004802 if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
Johan Hedberg1a4d3c42013-03-15 17:07:08 -05004803 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4804 hdev);
4805 goto unlock;
4806 }
4807
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004808 if (!hdev_is_powered(hdev)) {
Marcel Holtmannce05d602015-03-13 02:11:03 -07004809 hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
Johan Hedberg406ef2a2015-03-10 20:14:27 +02004810 err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE,
4811 hdev);
4812 new_settings(hdev, sk);
4813 goto unlock;
4814 }
4815
Johan Hedberg33e38b32013-03-15 17:07:05 -05004816 cmd = mgmt_pending_add(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev,
4817 data, len);
4818 if (!cmd) {
4819 err = -ENOMEM;
4820 goto unlock;
4821 }
4822
4823 hci_req_init(&req, hdev);
4824
Johan Hedberg406d7802013-03-15 17:07:09 -05004825 write_fast_connectable(&req, cp->val);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004826
4827 err = hci_req_run(&req, fast_connectable_complete);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004828 if (err < 0) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004829 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
4830 MGMT_STATUS_FAILED);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004831 mgmt_pending_remove(cmd);
Antti Julkuf6422ec2011-06-22 13:11:56 +03004832 }
4833
Johan Hedberg33e38b32013-03-15 17:07:05 -05004834unlock:
Antti Julkuf6422ec2011-06-22 13:11:56 +03004835 hci_dev_unlock(hdev);
Johan Hedberg33e38b32013-03-15 17:07:05 -05004836
Antti Julkuf6422ec2011-06-22 13:11:56 +03004837 return err;
4838}
4839
Marcel Holtmann1904a852015-01-11 13:50:44 -08004840static void set_bredr_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg0663ca22013-10-02 13:43:14 +03004841{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004842 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004843
4844 BT_DBG("status 0x%02x", status);
4845
4846 hci_dev_lock(hdev);
4847
4848 cmd = mgmt_pending_find(MGMT_OP_SET_BREDR, hdev);
4849 if (!cmd)
4850 goto unlock;
4851
4852 if (status) {
4853 u8 mgmt_err = mgmt_status(status);
4854
4855 /* We need to restore the flag if related HCI commands
4856 * failed.
4857 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004858 hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004859
Johan Hedberga69e8372015-03-06 21:08:53 +02004860 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004861 } else {
4862 send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
4863 new_settings(hdev, cmd->sk);
4864 }
4865
4866 mgmt_pending_remove(cmd);
4867
4868unlock:
4869 hci_dev_unlock(hdev);
4870}
4871
4872static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
4873{
4874 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004875 struct mgmt_pending_cmd *cmd;
Johan Hedberg0663ca22013-10-02 13:43:14 +03004876 struct hci_request req;
4877 int err;
4878
4879 BT_DBG("request for %s", hdev->name);
4880
4881 if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02004882 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4883 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004884
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004885 if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02004886 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4887 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004888
4889 if (cp->val != 0x00 && cp->val != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02004890 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4891 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004892
4893 hci_dev_lock(hdev);
4894
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004895 if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg0663ca22013-10-02 13:43:14 +03004896 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4897 goto unlock;
4898 }
4899
4900 if (!hdev_is_powered(hdev)) {
4901 if (!cp->val) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07004902 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
4903 hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
4904 hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
4905 hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
4906 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004907 }
4908
Marcel Holtmannce05d602015-03-13 02:11:03 -07004909 hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004910
4911 err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
4912 if (err < 0)
4913 goto unlock;
4914
4915 err = new_settings(hdev, sk);
4916 goto unlock;
4917 }
4918
4919 /* Reject disabling when powered on */
4920 if (!cp->val) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004921 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4922 MGMT_STATUS_REJECTED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004923 goto unlock;
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004924 } else {
4925 /* When configuring a dual-mode controller to operate
4926 * with LE only and using a static address, then switching
4927 * BR/EDR back on is not allowed.
4928 *
4929 * Dual-mode controllers shall operate with the public
4930 * address as its identity address for BR/EDR and LE. So
4931 * reject the attempt to create an invalid configuration.
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004932 *
4933 * The same restrictions applies when secure connections
4934 * has been enabled. For BR/EDR this is a controller feature
4935 * while for LE it is a host stack feature. This means that
4936 * switching BR/EDR back on when secure connections has been
4937 * enabled is not a supported transaction.
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004938 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004939 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Marcel Holtmann3a5486e2015-01-22 11:15:21 -08004940 (bacmp(&hdev->static_addr, BDADDR_ANY) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07004941 hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004942 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4943 MGMT_STATUS_REJECTED);
Marcel Holtmann111e4bc2015-01-14 14:40:42 -08004944 goto unlock;
4945 }
Johan Hedberg0663ca22013-10-02 13:43:14 +03004946 }
4947
4948 if (mgmt_pending_find(MGMT_OP_SET_BREDR, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004949 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
4950 MGMT_STATUS_BUSY);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004951 goto unlock;
4952 }
4953
4954 cmd = mgmt_pending_add(sk, MGMT_OP_SET_BREDR, hdev, data, len);
4955 if (!cmd) {
4956 err = -ENOMEM;
4957 goto unlock;
4958 }
4959
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004960 /* We need to flip the bit already here so that update_adv_data
Johan Hedberg0663ca22013-10-02 13:43:14 +03004961 * generates the correct flags.
4962 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07004963 hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
Johan Hedberg0663ca22013-10-02 13:43:14 +03004964
4965 hci_req_init(&req, hdev);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004966
Johan Hedberg432df052014-08-01 11:13:31 +03004967 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02004968 __hci_update_page_scan(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004969
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07004970 /* Since only the advertising data flags will change, there
4971 * is no need to update the scan response data.
4972 */
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07004973 update_adv_data(&req);
Johan Hedbergaa8af462013-10-14 21:15:26 +03004974
Johan Hedberg0663ca22013-10-02 13:43:14 +03004975 err = hci_req_run(&req, set_bredr_complete);
4976 if (err < 0)
4977 mgmt_pending_remove(cmd);
4978
4979unlock:
4980 hci_dev_unlock(hdev);
4981 return err;
4982}
4983
Johan Hedberga1443f52015-01-23 15:42:46 +02004984static void sc_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
4985{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02004986 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02004987 struct mgmt_mode *cp;
4988
4989 BT_DBG("%s status %u", hdev->name, status);
4990
4991 hci_dev_lock(hdev);
4992
4993 cmd = mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev);
4994 if (!cmd)
4995 goto unlock;
4996
4997 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02004998 mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
4999 mgmt_status(status));
Johan Hedberga1443f52015-01-23 15:42:46 +02005000 goto remove;
5001 }
5002
5003 cp = cmd->param;
5004
5005 switch (cp->val) {
5006 case 0x00:
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005007 hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
5008 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005009 break;
5010 case 0x01:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005011 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005012 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005013 break;
5014 case 0x02:
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005015 hci_dev_set_flag(hdev, HCI_SC_ENABLED);
5016 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Johan Hedberga1443f52015-01-23 15:42:46 +02005017 break;
5018 }
5019
5020 send_settings_rsp(cmd->sk, MGMT_OP_SET_SECURE_CONN, hdev);
5021 new_settings(hdev, cmd->sk);
5022
5023remove:
5024 mgmt_pending_remove(cmd);
5025unlock:
5026 hci_dev_unlock(hdev);
5027}
5028
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005029static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
5030 void *data, u16 len)
5031{
5032 struct mgmt_mode *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005033 struct mgmt_pending_cmd *cmd;
Johan Hedberga1443f52015-01-23 15:42:46 +02005034 struct hci_request req;
Johan Hedberga3209692014-05-26 11:23:35 +03005035 u8 val;
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005036 int err;
5037
5038 BT_DBG("request for %s", hdev->name);
5039
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005040 if (!lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005041 !hci_dev_test_flag(hdev, HCI_LE_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005042 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5043 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005044
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005045 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
Johan Hedberg59200282015-01-28 19:56:00 +02005046 lmp_sc_capable(hdev) &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005047 !hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
Johan Hedberga69e8372015-03-06 21:08:53 +02005048 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5049 MGMT_STATUS_REJECTED);
Marcel Holtmanned93ec62015-01-22 11:15:22 -08005050
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005051 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005052 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005053 MGMT_STATUS_INVALID_PARAMS);
5054
5055 hci_dev_lock(hdev);
5056
Marcel Holtmann05b3c3e2014-12-31 14:43:18 -08005057 if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005058 !hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005059 bool changed;
5060
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005061 if (cp->val) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005062 changed = !hci_dev_test_and_set_flag(hdev,
5063 HCI_SC_ENABLED);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005064 if (cp->val == 0x02)
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005065 hci_dev_set_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005066 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005067 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005068 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005069 changed = hci_dev_test_and_clear_flag(hdev,
5070 HCI_SC_ENABLED);
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005071 hci_dev_clear_flag(hdev, HCI_SC_ONLY);
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005072 }
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005073
5074 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5075 if (err < 0)
5076 goto failed;
5077
5078 if (changed)
5079 err = new_settings(hdev, sk);
5080
5081 goto failed;
5082 }
5083
5084 if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02005085 err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
5086 MGMT_STATUS_BUSY);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005087 goto failed;
5088 }
5089
Marcel Holtmann0ab04a92014-02-01 09:19:57 -08005090 val = !!cp->val;
5091
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005092 if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
5093 (cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005094 err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
5095 goto failed;
5096 }
5097
5098 cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
5099 if (!cmd) {
5100 err = -ENOMEM;
5101 goto failed;
5102 }
5103
Johan Hedberga1443f52015-01-23 15:42:46 +02005104 hci_req_init(&req, hdev);
5105 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, 1, &val);
5106 err = hci_req_run(&req, sc_enable_complete);
Marcel Holtmanneac83dc2014-01-10 02:07:23 -08005107 if (err < 0) {
5108 mgmt_pending_remove(cmd);
5109 goto failed;
5110 }
5111
5112failed:
5113 hci_dev_unlock(hdev);
5114 return err;
5115}
5116
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005117static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
5118 void *data, u16 len)
5119{
5120 struct mgmt_mode *cp = data;
Johan Hedbergb97109792014-06-24 14:00:28 +03005121 bool changed, use_changed;
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005122 int err;
5123
5124 BT_DBG("request for %s", hdev->name);
5125
Johan Hedbergb97109792014-06-24 14:00:28 +03005126 if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
Johan Hedberga69e8372015-03-06 21:08:53 +02005127 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
5128 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005129
5130 hci_dev_lock(hdev);
5131
5132 if (cp->val)
Marcel Holtmann238be782015-03-13 02:11:06 -07005133 changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005134 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005135 changed = hci_dev_test_and_clear_flag(hdev,
5136 HCI_KEEP_DEBUG_KEYS);
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005137
Johan Hedbergb97109792014-06-24 14:00:28 +03005138 if (cp->val == 0x02)
Marcel Holtmann238be782015-03-13 02:11:06 -07005139 use_changed = !hci_dev_test_and_set_flag(hdev,
5140 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005141 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005142 use_changed = hci_dev_test_and_clear_flag(hdev,
5143 HCI_USE_DEBUG_KEYS);
Johan Hedbergb97109792014-06-24 14:00:28 +03005144
5145 if (hdev_is_powered(hdev) && use_changed &&
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07005146 hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
Johan Hedbergb97109792014-06-24 14:00:28 +03005147 u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
5148 hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
5149 sizeof(mode), &mode);
5150 }
5151
Marcel Holtmann4e39ac82014-01-31 11:55:22 -08005152 err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
5153 if (err < 0)
5154 goto unlock;
5155
5156 if (changed)
5157 err = new_settings(hdev, sk);
5158
5159unlock:
5160 hci_dev_unlock(hdev);
5161 return err;
5162}
5163
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005164static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5165 u16 len)
5166{
5167 struct mgmt_cp_set_privacy *cp = cp_data;
5168 bool changed;
5169 int err;
5170
5171 BT_DBG("request for %s", hdev->name);
5172
5173 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005174 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5175 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005176
5177 if (cp->privacy != 0x00 && cp->privacy != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02005178 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5179 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005180
5181 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005182 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
5183 MGMT_STATUS_REJECTED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005184
5185 hci_dev_lock(hdev);
5186
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005187 /* If user space supports this command it is also expected to
5188 * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
5189 */
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005190 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedbergc21c0ea2014-02-24 11:10:30 +02005191
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005192 if (cp->privacy) {
Marcel Holtmann238be782015-03-13 02:11:06 -07005193 changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005194 memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005195 hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005196 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07005197 changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005198 memset(hdev->irk, 0, sizeof(hdev->irk));
Marcel Holtmanna358dc12015-03-13 02:11:02 -07005199 hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
Johan Hedberg62b04cd2014-02-23 19:42:27 +02005200 }
5201
5202 err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
5203 if (err < 0)
5204 goto unlock;
5205
5206 if (changed)
5207 err = new_settings(hdev, sk);
5208
5209unlock:
5210 hci_dev_unlock(hdev);
5211 return err;
5212}
5213
Johan Hedberg41edf162014-02-18 10:19:35 +02005214static bool irk_is_valid(struct mgmt_irk_info *irk)
5215{
5216 switch (irk->addr.type) {
5217 case BDADDR_LE_PUBLIC:
5218 return true;
5219
5220 case BDADDR_LE_RANDOM:
5221 /* Two most significant bits shall be set */
5222 if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5223 return false;
5224 return true;
5225 }
5226
5227 return false;
5228}
5229
5230static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
5231 u16 len)
5232{
5233 struct mgmt_cp_load_irks *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005234 const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
5235 sizeof(struct mgmt_irk_info));
Johan Hedberg41edf162014-02-18 10:19:35 +02005236 u16 irk_count, expected_len;
5237 int i, err;
5238
5239 BT_DBG("request for %s", hdev->name);
5240
5241 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005242 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5243 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberg41edf162014-02-18 10:19:35 +02005244
5245 irk_count = __le16_to_cpu(cp->irk_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005246 if (irk_count > max_irk_count) {
5247 BT_ERR("load_irks: too big irk_count value %u", irk_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005248 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5249 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005250 }
Johan Hedberg41edf162014-02-18 10:19:35 +02005251
5252 expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info);
5253 if (expected_len != len) {
5254 BT_ERR("load_irks: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005255 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005256 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
5257 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005258 }
5259
5260 BT_DBG("%s irk_count %u", hdev->name, irk_count);
5261
5262 for (i = 0; i < irk_count; i++) {
5263 struct mgmt_irk_info *key = &cp->irks[i];
5264
5265 if (!irk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005266 return mgmt_cmd_status(sk, hdev->id,
5267 MGMT_OP_LOAD_IRKS,
5268 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg41edf162014-02-18 10:19:35 +02005269 }
5270
5271 hci_dev_lock(hdev);
5272
5273 hci_smp_irks_clear(hdev);
5274
5275 for (i = 0; i < irk_count; i++) {
5276 struct mgmt_irk_info *irk = &cp->irks[i];
5277 u8 addr_type;
5278
5279 if (irk->addr.type == BDADDR_LE_PUBLIC)
5280 addr_type = ADDR_LE_DEV_PUBLIC;
5281 else
5282 addr_type = ADDR_LE_DEV_RANDOM;
5283
5284 hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val,
5285 BDADDR_ANY);
5286 }
5287
Marcel Holtmanna1536da2015-03-13 02:11:01 -07005288 hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
Johan Hedberg41edf162014-02-18 10:19:35 +02005289
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005290 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
Johan Hedberg41edf162014-02-18 10:19:35 +02005291
5292 hci_dev_unlock(hdev);
5293
5294 return err;
5295}
5296
Johan Hedberg3f706b72013-01-20 14:27:16 +02005297static bool ltk_is_valid(struct mgmt_ltk_info *key)
5298{
5299 if (key->master != 0x00 && key->master != 0x01)
5300 return false;
Marcel Holtmann490cb0b2014-02-16 12:59:05 -08005301
5302 switch (key->addr.type) {
5303 case BDADDR_LE_PUBLIC:
5304 return true;
5305
5306 case BDADDR_LE_RANDOM:
5307 /* Two most significant bits shall be set */
5308 if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
5309 return false;
5310 return true;
5311 }
5312
5313 return false;
Johan Hedberg3f706b72013-01-20 14:27:16 +02005314}
5315
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005316static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03005317 void *cp_data, u16 len)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005318{
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005319 struct mgmt_cp_load_long_term_keys *cp = cp_data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03005320 const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
5321 sizeof(struct mgmt_ltk_info));
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005322 u16 key_count, expected_len;
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005323 int i, err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005324
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005325 BT_DBG("request for %s", hdev->name);
5326
5327 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02005328 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5329 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanncf99ba12013-10-02 21:16:08 -07005330
Marcel Holtmann1f350c82012-03-12 20:31:08 -07005331 key_count = __le16_to_cpu(cp->key_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005332 if (key_count > max_key_count) {
5333 BT_ERR("load_ltks: too big key_count value %u", key_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02005334 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5335 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03005336 }
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005337
5338 expected_len = sizeof(*cp) + key_count *
5339 sizeof(struct mgmt_ltk_info);
5340 if (expected_len != len) {
5341 BT_ERR("load_keys: expected %u bytes, got %u bytes",
Johan Hedberg2606ecb2014-03-07 15:04:13 +02005342 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02005343 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
5344 MGMT_STATUS_INVALID_PARAMS);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005345 }
5346
Johan Hedbergbdb6d972012-02-28 06:13:32 +02005347 BT_DBG("%s key_count %u", hdev->name, key_count);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005348
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005349 for (i = 0; i < key_count; i++) {
5350 struct mgmt_ltk_info *key = &cp->keys[i];
5351
Johan Hedberg3f706b72013-01-20 14:27:16 +02005352 if (!ltk_is_valid(key))
Johan Hedberga69e8372015-03-06 21:08:53 +02005353 return mgmt_cmd_status(sk, hdev->id,
5354 MGMT_OP_LOAD_LONG_TERM_KEYS,
5355 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg54ad6d82013-01-20 14:27:15 +02005356 }
5357
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005358 hci_dev_lock(hdev);
5359
5360 hci_smp_ltks_clear(hdev);
5361
5362 for (i = 0; i < key_count; i++) {
5363 struct mgmt_ltk_info *key = &cp->keys[i];
Johan Hedbergd7b25452014-05-23 13:19:53 +03005364 u8 type, addr_type, authenticated;
Marcel Holtmann79d95a12013-10-13 03:57:38 -07005365
5366 if (key->addr.type == BDADDR_LE_PUBLIC)
5367 addr_type = ADDR_LE_DEV_PUBLIC;
5368 else
5369 addr_type = ADDR_LE_DEV_RANDOM;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005370
Johan Hedberg61b43352014-05-29 19:36:53 +03005371 switch (key->type) {
5372 case MGMT_LTK_UNAUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005373 authenticated = 0x00;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005374 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005375 break;
5376 case MGMT_LTK_AUTHENTICATED:
Johan Hedbergd7b25452014-05-23 13:19:53 +03005377 authenticated = 0x01;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005378 type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
Johan Hedberg61b43352014-05-29 19:36:53 +03005379 break;
Johan Hedberg23fb8de2014-05-23 13:15:37 +03005380 case MGMT_LTK_P256_UNAUTH:
5381 authenticated = 0x00;
5382 type = SMP_LTK_P256;
5383 break;
5384 case MGMT_LTK_P256_AUTH:
5385 authenticated = 0x01;
5386 type = SMP_LTK_P256;
5387 break;
5388 case MGMT_LTK_P256_DEBUG:
5389 authenticated = 0x00;
5390 type = SMP_LTK_P256_DEBUG;
Johan Hedberg61b43352014-05-29 19:36:53 +03005391 default:
5392 continue;
5393 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03005394
Johan Hedberg35d70272014-02-19 14:57:47 +02005395 hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type,
Johan Hedbergd7b25452014-05-23 13:19:53 +03005396 authenticated, key->val, key->enc_size, key->ediv,
Johan Hedberg35d70272014-02-19 14:57:47 +02005397 key->rand);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005398 }
5399
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005400 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005401 NULL, 0);
5402
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005403 hci_dev_unlock(hdev);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005404
Johan Hedberg715a5bf2013-01-09 15:29:34 +02005405 return err;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03005406}
5407
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005408static int conn_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005409{
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005410 struct hci_conn *conn = cmd->user_data;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005411 struct mgmt_rp_get_conn_info rp;
Johan Hedberg9df74652014-12-19 22:26:03 +02005412 int err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005413
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005414 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005415
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005416 if (status == MGMT_STATUS_SUCCESS) {
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005417 rp.rssi = conn->rssi;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005418 rp.tx_power = conn->tx_power;
5419 rp.max_tx_power = conn->max_tx_power;
5420 } else {
5421 rp.rssi = HCI_RSSI_INVALID;
5422 rp.tx_power = HCI_TX_POWER_INVALID;
5423 rp.max_tx_power = HCI_TX_POWER_INVALID;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005424 }
5425
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005426 err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
5427 status, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005428
5429 hci_conn_drop(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005430 hci_conn_put(conn);
Johan Hedberg9df74652014-12-19 22:26:03 +02005431
5432 return err;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005433}
5434
Marcel Holtmann1904a852015-01-11 13:50:44 -08005435static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status,
5436 u16 opcode)
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005437{
5438 struct hci_cp_read_rssi *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005439 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005440 struct hci_conn *conn;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005441 u16 handle;
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005442 u8 status;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005443
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005444 BT_DBG("status 0x%02x", hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005445
5446 hci_dev_lock(hdev);
5447
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005448 /* Commands sent in request are either Read RSSI or Read Transmit Power
5449 * Level so we check which one was last sent to retrieve connection
5450 * handle. Both commands have handle as first parameter so it's safe to
5451 * cast data on the same command struct.
5452 *
5453 * First command sent is always Read RSSI and we fail only if it fails.
5454 * In other case we simply override error to indicate success as we
5455 * already remembered if TX power value is actually valid.
5456 */
5457 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5458 if (!cp) {
5459 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005460 status = MGMT_STATUS_SUCCESS;
5461 } else {
5462 status = mgmt_status(hci_status);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005463 }
5464
5465 if (!cp) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005466 BT_ERR("invalid sent_cmd in conn_info response");
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005467 goto unlock;
5468 }
5469
5470 handle = __le16_to_cpu(cp->handle);
5471 conn = hci_conn_hash_lookup_handle(hdev, handle);
5472 if (!conn) {
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005473 BT_ERR("unknown handle (%d) in conn_info response", handle);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005474 goto unlock;
5475 }
5476
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005477 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5478 if (!cmd)
5479 goto unlock;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005480
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005481 cmd->cmd_complete(cmd, status);
5482 mgmt_pending_remove(cmd);
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005483
5484unlock:
5485 hci_dev_unlock(hdev);
5486}
5487
5488static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5489 u16 len)
5490{
5491 struct mgmt_cp_get_conn_info *cp = data;
5492 struct mgmt_rp_get_conn_info rp;
5493 struct hci_conn *conn;
5494 unsigned long conn_info_age;
5495 int err = 0;
5496
5497 BT_DBG("%s", hdev->name);
5498
5499 memset(&rp, 0, sizeof(rp));
5500 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5501 rp.addr.type = cp->addr.type;
5502
5503 if (!bdaddr_type_is_valid(cp->addr.type))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005504 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5505 MGMT_STATUS_INVALID_PARAMS,
5506 &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005507
5508 hci_dev_lock(hdev);
5509
5510 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005511 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5512 MGMT_STATUS_NOT_POWERED, &rp,
5513 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005514 goto unlock;
5515 }
5516
5517 if (cp->addr.type == BDADDR_BREDR)
5518 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5519 &cp->addr.bdaddr);
5520 else
5521 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
5522
5523 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005524 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5525 MGMT_STATUS_NOT_CONNECTED, &rp,
5526 sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005527 goto unlock;
5528 }
5529
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005530 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005531 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5532 MGMT_STATUS_BUSY, &rp, sizeof(rp));
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005533 goto unlock;
5534 }
5535
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005536 /* To avoid client trying to guess when to poll again for information we
5537 * calculate conn info age as random value between min/max set in hdev.
5538 */
5539 conn_info_age = hdev->conn_info_min_age +
5540 prandom_u32_max(hdev->conn_info_max_age -
5541 hdev->conn_info_min_age);
5542
5543 /* Query controller to refresh cached values if they are too old or were
5544 * never read.
5545 */
Andrzej Kaczmarekf4e2dd52014-05-16 16:48:57 +02005546 if (time_after(jiffies, conn->conn_info_timestamp +
5547 msecs_to_jiffies(conn_info_age)) ||
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005548 !conn->conn_info_timestamp) {
5549 struct hci_request req;
5550 struct hci_cp_read_tx_power req_txp_cp;
5551 struct hci_cp_read_rssi req_rssi_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005552 struct mgmt_pending_cmd *cmd;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005553
5554 hci_req_init(&req, hdev);
5555 req_rssi_cp.handle = cpu_to_le16(conn->handle);
5556 hci_req_add(&req, HCI_OP_READ_RSSI, sizeof(req_rssi_cp),
5557 &req_rssi_cp);
5558
Andrzej Kaczmarekf7faab02014-05-14 13:43:04 +02005559 /* For LE links TX power does not change thus we don't need to
5560 * query for it once value is known.
5561 */
5562 if (!bdaddr_type_is_le(cp->addr.type) ||
5563 conn->tx_power == HCI_TX_POWER_INVALID) {
5564 req_txp_cp.handle = cpu_to_le16(conn->handle);
5565 req_txp_cp.type = 0x00;
5566 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5567 sizeof(req_txp_cp), &req_txp_cp);
5568 }
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005569
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005570 /* Max TX power needs to be read only once per connection */
5571 if (conn->max_tx_power == HCI_TX_POWER_INVALID) {
5572 req_txp_cp.handle = cpu_to_le16(conn->handle);
5573 req_txp_cp.type = 0x01;
5574 hci_req_add(&req, HCI_OP_READ_TX_POWER,
5575 sizeof(req_txp_cp), &req_txp_cp);
5576 }
5577
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005578 err = hci_req_run(&req, conn_info_refresh_complete);
5579 if (err < 0)
5580 goto unlock;
5581
5582 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CONN_INFO, hdev,
5583 data, len);
5584 if (!cmd) {
5585 err = -ENOMEM;
5586 goto unlock;
5587 }
5588
5589 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005590 cmd->user_data = hci_conn_get(conn);
Johan Hedberg9981bdb2014-12-05 13:42:57 +02005591 cmd->cmd_complete = conn_info_cmd_complete;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005592
5593 conn->conn_info_timestamp = jiffies;
5594 } else {
5595 /* Cache is valid, just reply with values cached in hci_conn */
5596 rp.rssi = conn->rssi;
5597 rp.tx_power = conn->tx_power;
Andrzej Kaczmarekeed5daf2014-05-14 13:43:06 +02005598 rp.max_tx_power = conn->max_tx_power;
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005599
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005600 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5601 MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
Andrzej Kaczmarekdd983802014-05-14 13:43:03 +02005602 }
5603
5604unlock:
5605 hci_dev_unlock(hdev);
5606 return err;
5607}
5608
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005609static int clock_info_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
Johan Hedberg69487372014-12-05 13:36:07 +02005610{
5611 struct hci_conn *conn = cmd->user_data;
5612 struct mgmt_rp_get_clock_info rp;
5613 struct hci_dev *hdev;
Johan Hedberg9df74652014-12-19 22:26:03 +02005614 int err;
Johan Hedberg69487372014-12-05 13:36:07 +02005615
5616 memset(&rp, 0, sizeof(rp));
5617 memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
5618
5619 if (status)
5620 goto complete;
5621
5622 hdev = hci_dev_get(cmd->index);
5623 if (hdev) {
5624 rp.local_clock = cpu_to_le32(hdev->clock);
5625 hci_dev_put(hdev);
5626 }
5627
5628 if (conn) {
5629 rp.piconet_clock = cpu_to_le32(conn->clock);
5630 rp.accuracy = cpu_to_le16(conn->clock_accuracy);
5631 }
5632
5633complete:
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005634 err = mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
5635 sizeof(rp));
Johan Hedberg69487372014-12-05 13:36:07 +02005636
5637 if (conn) {
5638 hci_conn_drop(conn);
5639 hci_conn_put(conn);
5640 }
Johan Hedberg9df74652014-12-19 22:26:03 +02005641
5642 return err;
Johan Hedberg69487372014-12-05 13:36:07 +02005643}
5644
Marcel Holtmann1904a852015-01-11 13:50:44 -08005645static void get_clock_info_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg95868422014-06-28 17:54:07 +03005646{
Johan Hedberg95868422014-06-28 17:54:07 +03005647 struct hci_cp_read_clock *hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005648 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005649 struct hci_conn *conn;
5650
5651 BT_DBG("%s status %u", hdev->name, status);
5652
5653 hci_dev_lock(hdev);
5654
5655 hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
5656 if (!hci_cp)
5657 goto unlock;
5658
5659 if (hci_cp->which) {
5660 u16 handle = __le16_to_cpu(hci_cp->handle);
5661 conn = hci_conn_hash_lookup_handle(hdev, handle);
5662 } else {
5663 conn = NULL;
5664 }
5665
5666 cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn);
5667 if (!cmd)
5668 goto unlock;
5669
Johan Hedberg69487372014-12-05 13:36:07 +02005670 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberg95868422014-06-28 17:54:07 +03005671 mgmt_pending_remove(cmd);
Johan Hedberg95868422014-06-28 17:54:07 +03005672
5673unlock:
5674 hci_dev_unlock(hdev);
5675}
5676
5677static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
5678 u16 len)
5679{
5680 struct mgmt_cp_get_clock_info *cp = data;
5681 struct mgmt_rp_get_clock_info rp;
5682 struct hci_cp_read_clock hci_cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005683 struct mgmt_pending_cmd *cmd;
Johan Hedberg95868422014-06-28 17:54:07 +03005684 struct hci_request req;
5685 struct hci_conn *conn;
5686 int err;
5687
5688 BT_DBG("%s", hdev->name);
5689
5690 memset(&rp, 0, sizeof(rp));
5691 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5692 rp.addr.type = cp->addr.type;
5693
5694 if (cp->addr.type != BDADDR_BREDR)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005695 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5696 MGMT_STATUS_INVALID_PARAMS,
5697 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005698
5699 hci_dev_lock(hdev);
5700
5701 if (!hdev_is_powered(hdev)) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005702 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
5703 MGMT_STATUS_NOT_POWERED, &rp,
5704 sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005705 goto unlock;
5706 }
5707
5708 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
5709 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
5710 &cp->addr.bdaddr);
5711 if (!conn || conn->state != BT_CONNECTED) {
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005712 err = mgmt_cmd_complete(sk, hdev->id,
5713 MGMT_OP_GET_CLOCK_INFO,
5714 MGMT_STATUS_NOT_CONNECTED,
5715 &rp, sizeof(rp));
Johan Hedberg95868422014-06-28 17:54:07 +03005716 goto unlock;
5717 }
5718 } else {
5719 conn = NULL;
5720 }
5721
5722 cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
5723 if (!cmd) {
5724 err = -ENOMEM;
5725 goto unlock;
5726 }
5727
Johan Hedberg69487372014-12-05 13:36:07 +02005728 cmd->cmd_complete = clock_info_cmd_complete;
5729
Johan Hedberg95868422014-06-28 17:54:07 +03005730 hci_req_init(&req, hdev);
5731
5732 memset(&hci_cp, 0, sizeof(hci_cp));
5733 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5734
5735 if (conn) {
5736 hci_conn_hold(conn);
Johan Hedbergf8aaf9b2014-08-17 23:28:57 +03005737 cmd->user_data = hci_conn_get(conn);
Johan Hedberg95868422014-06-28 17:54:07 +03005738
5739 hci_cp.handle = cpu_to_le16(conn->handle);
5740 hci_cp.which = 0x01; /* Piconet clock */
5741 hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp);
5742 }
5743
5744 err = hci_req_run(&req, get_clock_info_complete);
5745 if (err < 0)
5746 mgmt_pending_remove(cmd);
5747
5748unlock:
5749 hci_dev_unlock(hdev);
5750 return err;
5751}
5752
Johan Hedberg5a154e62014-12-19 22:26:02 +02005753static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
5754{
5755 struct hci_conn *conn;
5756
5757 conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
5758 if (!conn)
5759 return false;
5760
5761 if (conn->dst_type != type)
5762 return false;
5763
5764 if (conn->state != BT_CONNECTED)
5765 return false;
5766
5767 return true;
5768}
5769
5770/* This function requires the caller holds hdev->lock */
5771static int hci_conn_params_set(struct hci_request *req, bdaddr_t *addr,
5772 u8 addr_type, u8 auto_connect)
5773{
5774 struct hci_dev *hdev = req->hdev;
5775 struct hci_conn_params *params;
5776
5777 params = hci_conn_params_add(hdev, addr, addr_type);
5778 if (!params)
5779 return -EIO;
5780
5781 if (params->auto_connect == auto_connect)
5782 return 0;
5783
5784 list_del_init(&params->action);
5785
5786 switch (auto_connect) {
5787 case HCI_AUTO_CONN_DISABLED:
5788 case HCI_AUTO_CONN_LINK_LOSS:
5789 __hci_update_background_scan(req);
5790 break;
5791 case HCI_AUTO_CONN_REPORT:
5792 list_add(&params->action, &hdev->pend_le_reports);
5793 __hci_update_background_scan(req);
5794 break;
5795 case HCI_AUTO_CONN_DIRECT:
5796 case HCI_AUTO_CONN_ALWAYS:
5797 if (!is_connected(hdev, addr, addr_type)) {
5798 list_add(&params->action, &hdev->pend_le_conns);
5799 __hci_update_background_scan(req);
5800 }
5801 break;
5802 }
5803
5804 params->auto_connect = auto_connect;
5805
5806 BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type,
5807 auto_connect);
5808
5809 return 0;
5810}
5811
Marcel Holtmann8afef092014-06-29 22:28:34 +02005812static void device_added(struct sock *sk, struct hci_dev *hdev,
5813 bdaddr_t *bdaddr, u8 type, u8 action)
5814{
5815 struct mgmt_ev_device_added ev;
5816
5817 bacpy(&ev.addr.bdaddr, bdaddr);
5818 ev.addr.type = type;
5819 ev.action = action;
5820
5821 mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
5822}
5823
Marcel Holtmann1904a852015-01-11 13:50:44 -08005824static void add_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg5a154e62014-12-19 22:26:02 +02005825{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005826 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005827
5828 BT_DBG("status 0x%02x", status);
5829
5830 hci_dev_lock(hdev);
5831
5832 cmd = mgmt_pending_find(MGMT_OP_ADD_DEVICE, hdev);
5833 if (!cmd)
5834 goto unlock;
5835
5836 cmd->cmd_complete(cmd, mgmt_status(status));
5837 mgmt_pending_remove(cmd);
5838
5839unlock:
5840 hci_dev_unlock(hdev);
5841}
5842
Marcel Holtmann2faade52014-06-29 19:44:03 +02005843static int add_device(struct sock *sk, struct hci_dev *hdev,
5844 void *data, u16 len)
5845{
5846 struct mgmt_cp_add_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005847 struct mgmt_pending_cmd *cmd;
Johan Hedberg5a154e62014-12-19 22:26:02 +02005848 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005849 u8 auto_conn, addr_type;
5850 int err;
5851
5852 BT_DBG("%s", hdev->name);
5853
Johan Hedberg66593582014-07-09 12:59:14 +03005854 if (!bdaddr_type_is_valid(cp->addr.type) ||
Marcel Holtmann2faade52014-06-29 19:44:03 +02005855 !bacmp(&cp->addr.bdaddr, BDADDR_ANY))
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005856 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5857 MGMT_STATUS_INVALID_PARAMS,
5858 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005859
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005860 if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
Johan Hedberg2a1afb52015-03-06 21:08:54 +02005861 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
5862 MGMT_STATUS_INVALID_PARAMS,
5863 &cp->addr, sizeof(cp->addr));
Marcel Holtmann2faade52014-06-29 19:44:03 +02005864
Johan Hedberg5a154e62014-12-19 22:26:02 +02005865 hci_req_init(&req, hdev);
5866
Marcel Holtmann2faade52014-06-29 19:44:03 +02005867 hci_dev_lock(hdev);
5868
Johan Hedberg5a154e62014-12-19 22:26:02 +02005869 cmd = mgmt_pending_add(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
5870 if (!cmd) {
5871 err = -ENOMEM;
5872 goto unlock;
5873 }
5874
5875 cmd->cmd_complete = addr_cmd_complete;
5876
Johan Hedberg66593582014-07-09 12:59:14 +03005877 if (cp->addr.type == BDADDR_BREDR) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005878 /* Only incoming connections action is supported for now */
Johan Hedberg66593582014-07-09 12:59:14 +03005879 if (cp->action != 0x01) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005880 err = cmd->cmd_complete(cmd,
5881 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005882 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03005883 goto unlock;
5884 }
5885
5886 err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr,
5887 cp->addr.type);
5888 if (err)
5889 goto unlock;
Johan Hedberga3974072014-07-09 12:59:15 +03005890
Johan Hedberg5a154e62014-12-19 22:26:02 +02005891 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03005892
Johan Hedberg66593582014-07-09 12:59:14 +03005893 goto added;
5894 }
5895
Marcel Holtmann2faade52014-06-29 19:44:03 +02005896 if (cp->addr.type == BDADDR_LE_PUBLIC)
5897 addr_type = ADDR_LE_DEV_PUBLIC;
5898 else
5899 addr_type = ADDR_LE_DEV_RANDOM;
5900
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005901 if (cp->action == 0x02)
Marcel Holtmann2faade52014-06-29 19:44:03 +02005902 auto_conn = HCI_AUTO_CONN_ALWAYS;
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02005903 else if (cp->action == 0x01)
5904 auto_conn = HCI_AUTO_CONN_DIRECT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005905 else
Johan Hedberga3451d22014-07-02 17:37:27 +03005906 auto_conn = HCI_AUTO_CONN_REPORT;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005907
Marcel Holtmannbf5b3c82014-06-30 12:34:39 +02005908 /* If the connection parameters don't exist for this device,
5909 * they will be created and configured with defaults.
5910 */
Johan Hedberg5a154e62014-12-19 22:26:02 +02005911 if (hci_conn_params_set(&req, &cp->addr.bdaddr, addr_type,
Marcel Holtmannd06b50c2014-07-01 12:11:06 +02005912 auto_conn) < 0) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005913 err = cmd->cmd_complete(cmd, MGMT_STATUS_FAILED);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005914 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005915 goto unlock;
5916 }
5917
Johan Hedberg66593582014-07-09 12:59:14 +03005918added:
Marcel Holtmann8afef092014-06-29 22:28:34 +02005919 device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
5920
Johan Hedberg5a154e62014-12-19 22:26:02 +02005921 err = hci_req_run(&req, add_device_complete);
5922 if (err < 0) {
5923 /* ENODATA means no HCI commands were needed (e.g. if
5924 * the adapter is powered off).
5925 */
Johan Hedberg9df74652014-12-19 22:26:03 +02005926 if (err == -ENODATA)
5927 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg5a154e62014-12-19 22:26:02 +02005928 mgmt_pending_remove(cmd);
5929 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02005930
5931unlock:
5932 hci_dev_unlock(hdev);
5933 return err;
5934}
5935
Marcel Holtmann8afef092014-06-29 22:28:34 +02005936static void device_removed(struct sock *sk, struct hci_dev *hdev,
5937 bdaddr_t *bdaddr, u8 type)
5938{
5939 struct mgmt_ev_device_removed ev;
5940
5941 bacpy(&ev.addr.bdaddr, bdaddr);
5942 ev.addr.type = type;
5943
5944 mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
5945}
5946
Marcel Holtmann1904a852015-01-11 13:50:44 -08005947static void remove_device_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005948{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005949 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005950
5951 BT_DBG("status 0x%02x", status);
5952
5953 hci_dev_lock(hdev);
5954
5955 cmd = mgmt_pending_find(MGMT_OP_REMOVE_DEVICE, hdev);
5956 if (!cmd)
5957 goto unlock;
5958
5959 cmd->cmd_complete(cmd, mgmt_status(status));
5960 mgmt_pending_remove(cmd);
5961
5962unlock:
5963 hci_dev_unlock(hdev);
5964}
5965
Marcel Holtmann2faade52014-06-29 19:44:03 +02005966static int remove_device(struct sock *sk, struct hci_dev *hdev,
5967 void *data, u16 len)
5968{
5969 struct mgmt_cp_remove_device *cp = data;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02005970 struct mgmt_pending_cmd *cmd;
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005971 struct hci_request req;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005972 int err;
5973
5974 BT_DBG("%s", hdev->name);
5975
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005976 hci_req_init(&req, hdev);
5977
Marcel Holtmann2faade52014-06-29 19:44:03 +02005978 hci_dev_lock(hdev);
5979
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005980 cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_DEVICE, hdev, data, len);
5981 if (!cmd) {
5982 err = -ENOMEM;
5983 goto unlock;
5984 }
5985
5986 cmd->cmd_complete = addr_cmd_complete;
5987
Marcel Holtmann2faade52014-06-29 19:44:03 +02005988 if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
Johan Hedbergc71593d2014-07-02 17:37:28 +03005989 struct hci_conn_params *params;
Marcel Holtmann2faade52014-06-29 19:44:03 +02005990 u8 addr_type;
5991
Johan Hedberg66593582014-07-09 12:59:14 +03005992 if (!bdaddr_type_is_valid(cp->addr.type)) {
Johan Hedberg9df74652014-12-19 22:26:03 +02005993 err = cmd->cmd_complete(cmd,
5994 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02005995 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02005996 goto unlock;
5997 }
5998
Johan Hedberg66593582014-07-09 12:59:14 +03005999 if (cp->addr.type == BDADDR_BREDR) {
6000 err = hci_bdaddr_list_del(&hdev->whitelist,
6001 &cp->addr.bdaddr,
6002 cp->addr.type);
6003 if (err) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006004 err = cmd->cmd_complete(cmd,
6005 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006006 mgmt_pending_remove(cmd);
Johan Hedberg66593582014-07-09 12:59:14 +03006007 goto unlock;
6008 }
6009
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006010 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006011
Johan Hedberg66593582014-07-09 12:59:14 +03006012 device_removed(sk, hdev, &cp->addr.bdaddr,
6013 cp->addr.type);
6014 goto complete;
6015 }
6016
Marcel Holtmann2faade52014-06-29 19:44:03 +02006017 if (cp->addr.type == BDADDR_LE_PUBLIC)
6018 addr_type = ADDR_LE_DEV_PUBLIC;
6019 else
6020 addr_type = ADDR_LE_DEV_RANDOM;
6021
Johan Hedbergc71593d2014-07-02 17:37:28 +03006022 params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
6023 addr_type);
6024 if (!params) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006025 err = cmd->cmd_complete(cmd,
6026 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006027 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006028 goto unlock;
6029 }
6030
6031 if (params->auto_connect == HCI_AUTO_CONN_DISABLED) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006032 err = cmd->cmd_complete(cmd,
6033 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006034 mgmt_pending_remove(cmd);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006035 goto unlock;
6036 }
6037
Johan Hedbergd1dbf122014-07-04 16:17:23 +03006038 list_del(&params->action);
Johan Hedbergc71593d2014-07-02 17:37:28 +03006039 list_del(&params->list);
6040 kfree(params);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006041 __hci_update_background_scan(&req);
Marcel Holtmann8afef092014-06-29 22:28:34 +02006042
6043 device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006044 } else {
Johan Hedberg19de0822014-07-06 13:06:51 +03006045 struct hci_conn_params *p, *tmp;
Johan Hedberg66593582014-07-09 12:59:14 +03006046 struct bdaddr_list *b, *btmp;
Johan Hedberg19de0822014-07-06 13:06:51 +03006047
Marcel Holtmann2faade52014-06-29 19:44:03 +02006048 if (cp->addr.type) {
Johan Hedberg9df74652014-12-19 22:26:03 +02006049 err = cmd->cmd_complete(cmd,
6050 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006051 mgmt_pending_remove(cmd);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006052 goto unlock;
6053 }
6054
Johan Hedberg66593582014-07-09 12:59:14 +03006055 list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) {
6056 device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
6057 list_del(&b->list);
6058 kfree(b);
6059 }
6060
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006061 __hci_update_page_scan(&req);
Johan Hedberga3974072014-07-09 12:59:15 +03006062
Johan Hedberg19de0822014-07-06 13:06:51 +03006063 list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
6064 if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
6065 continue;
6066 device_removed(sk, hdev, &p->addr, p->addr_type);
6067 list_del(&p->action);
6068 list_del(&p->list);
6069 kfree(p);
6070 }
6071
6072 BT_DBG("All LE connection parameters were removed");
6073
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006074 __hci_update_background_scan(&req);
Marcel Holtmann2faade52014-06-29 19:44:03 +02006075 }
6076
Johan Hedberg66593582014-07-09 12:59:14 +03006077complete:
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006078 err = hci_req_run(&req, remove_device_complete);
6079 if (err < 0) {
6080 /* ENODATA means no HCI commands were needed (e.g. if
6081 * the adapter is powered off).
6082 */
Johan Hedberg9df74652014-12-19 22:26:03 +02006083 if (err == -ENODATA)
6084 err = cmd->cmd_complete(cmd, MGMT_STATUS_SUCCESS);
Johan Hedberg51ef3eb2014-12-19 22:26:01 +02006085 mgmt_pending_remove(cmd);
6086 }
Marcel Holtmann2faade52014-06-29 19:44:03 +02006087
6088unlock:
6089 hci_dev_unlock(hdev);
6090 return err;
6091}
6092
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006093static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
6094 u16 len)
6095{
6096 struct mgmt_cp_load_conn_param *cp = data;
Johan Hedbergba1d6932014-07-03 13:52:27 +03006097 const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
6098 sizeof(struct mgmt_conn_param));
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006099 u16 param_count, expected_len;
6100 int i;
6101
6102 if (!lmp_le_capable(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006103 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6104 MGMT_STATUS_NOT_SUPPORTED);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006105
6106 param_count = __le16_to_cpu(cp->param_count);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006107 if (param_count > max_param_count) {
6108 BT_ERR("load_conn_param: too big param_count value %u",
6109 param_count);
Johan Hedberga69e8372015-03-06 21:08:53 +02006110 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6111 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergba1d6932014-07-03 13:52:27 +03006112 }
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006113
6114 expected_len = sizeof(*cp) + param_count *
6115 sizeof(struct mgmt_conn_param);
6116 if (expected_len != len) {
6117 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
6118 expected_len, len);
Johan Hedberga69e8372015-03-06 21:08:53 +02006119 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
6120 MGMT_STATUS_INVALID_PARAMS);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006121 }
6122
6123 BT_DBG("%s param_count %u", hdev->name, param_count);
6124
6125 hci_dev_lock(hdev);
6126
6127 hci_conn_params_clear_disabled(hdev);
6128
6129 for (i = 0; i < param_count; i++) {
6130 struct mgmt_conn_param *param = &cp->params[i];
6131 struct hci_conn_params *hci_param;
6132 u16 min, max, latency, timeout;
6133 u8 addr_type;
6134
6135 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
6136 param->addr.type);
6137
6138 if (param->addr.type == BDADDR_LE_PUBLIC) {
6139 addr_type = ADDR_LE_DEV_PUBLIC;
6140 } else if (param->addr.type == BDADDR_LE_RANDOM) {
6141 addr_type = ADDR_LE_DEV_RANDOM;
6142 } else {
6143 BT_ERR("Ignoring invalid connection parameters");
6144 continue;
6145 }
6146
6147 min = le16_to_cpu(param->min_interval);
6148 max = le16_to_cpu(param->max_interval);
6149 latency = le16_to_cpu(param->latency);
6150 timeout = le16_to_cpu(param->timeout);
6151
6152 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
6153 min, max, latency, timeout);
6154
6155 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
6156 BT_ERR("Ignoring invalid connection parameters");
6157 continue;
6158 }
6159
6160 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
6161 addr_type);
6162 if (!hci_param) {
6163 BT_ERR("Failed to add connection parameters");
6164 continue;
6165 }
6166
6167 hci_param->conn_min_interval = min;
6168 hci_param->conn_max_interval = max;
6169 hci_param->conn_latency = latency;
6170 hci_param->supervision_timeout = timeout;
6171 }
6172
6173 hci_dev_unlock(hdev);
6174
Johan Hedberg2a1afb52015-03-06 21:08:54 +02006175 return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
6176 NULL, 0);
Johan Hedberga26f3dc2014-07-02 17:37:29 +03006177}
6178
Marcel Holtmanndbece372014-07-04 18:11:55 +02006179static int set_external_config(struct sock *sk, struct hci_dev *hdev,
6180 void *data, u16 len)
6181{
6182 struct mgmt_cp_set_external_config *cp = data;
6183 bool changed;
6184 int err;
6185
6186 BT_DBG("%s", hdev->name);
6187
6188 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006189 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6190 MGMT_STATUS_REJECTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006191
6192 if (cp->config != 0x00 && cp->config != 0x01)
Johan Hedberga69e8372015-03-06 21:08:53 +02006193 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6194 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006195
6196 if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
Johan Hedberga69e8372015-03-06 21:08:53 +02006197 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
6198 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006199
6200 hci_dev_lock(hdev);
6201
6202 if (cp->config)
Marcel Holtmann238be782015-03-13 02:11:06 -07006203 changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006204 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07006205 changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
Marcel Holtmanndbece372014-07-04 18:11:55 +02006206
6207 err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
6208 if (err < 0)
6209 goto unlock;
6210
6211 if (!changed)
6212 goto unlock;
6213
Marcel Holtmannf4537c02014-07-04 19:06:23 +02006214 err = new_options(hdev, sk);
6215
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006216 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
Marcel Holtmanndbece372014-07-04 18:11:55 +02006217 mgmt_index_removed(hdev);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006218
Marcel Holtmann516018a2015-03-13 02:11:04 -07006219 if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006220 hci_dev_set_flag(hdev, HCI_CONFIG);
6221 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006222
6223 queue_work(hdev->req_workqueue, &hdev->power_on);
6224 } else {
Marcel Holtmann5ea234d2014-07-06 12:11:16 +02006225 set_bit(HCI_RAW, &hdev->flags);
Marcel Holtmannd603b76b2014-07-06 12:11:14 +02006226 mgmt_index_added(hdev);
6227 }
Marcel Holtmanndbece372014-07-04 18:11:55 +02006228 }
6229
6230unlock:
6231 hci_dev_unlock(hdev);
6232 return err;
6233}
6234
Marcel Holtmann9713c172014-07-06 12:11:15 +02006235static int set_public_address(struct sock *sk, struct hci_dev *hdev,
6236 void *data, u16 len)
6237{
6238 struct mgmt_cp_set_public_address *cp = data;
6239 bool changed;
6240 int err;
6241
6242 BT_DBG("%s", hdev->name);
6243
6244 if (hdev_is_powered(hdev))
Johan Hedberga69e8372015-03-06 21:08:53 +02006245 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6246 MGMT_STATUS_REJECTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006247
6248 if (!bacmp(&cp->bdaddr, BDADDR_ANY))
Johan Hedberga69e8372015-03-06 21:08:53 +02006249 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6250 MGMT_STATUS_INVALID_PARAMS);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006251
6252 if (!hdev->set_bdaddr)
Johan Hedberga69e8372015-03-06 21:08:53 +02006253 return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
6254 MGMT_STATUS_NOT_SUPPORTED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006255
6256 hci_dev_lock(hdev);
6257
6258 changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
6259 bacpy(&hdev->public_addr, &cp->bdaddr);
6260
6261 err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
6262 if (err < 0)
6263 goto unlock;
6264
6265 if (!changed)
6266 goto unlock;
6267
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006268 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
Marcel Holtmann9713c172014-07-06 12:11:15 +02006269 err = new_options(hdev, sk);
6270
6271 if (is_configured(hdev)) {
6272 mgmt_index_removed(hdev);
6273
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006274 hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006275
Marcel Holtmanna1536da2015-03-13 02:11:01 -07006276 hci_dev_set_flag(hdev, HCI_CONFIG);
6277 hci_dev_set_flag(hdev, HCI_AUTO_OFF);
Marcel Holtmann9713c172014-07-06 12:11:15 +02006278
6279 queue_work(hdev->req_workqueue, &hdev->power_on);
6280 }
6281
6282unlock:
6283 hci_dev_unlock(hdev);
6284 return err;
6285}
6286
Marcel Holtmannbea41602015-03-14 22:43:17 -07006287static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
6288 u8 data_len)
6289{
6290 eir[eir_len++] = sizeof(type) + data_len;
6291 eir[eir_len++] = type;
6292 memcpy(&eir[eir_len], data, data_len);
6293 eir_len += data_len;
6294
6295 return eir_len;
6296}
6297
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006298static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
6299 void *data, u16 data_len)
6300{
6301 struct mgmt_cp_read_local_oob_ext_data *cp = data;
6302 struct mgmt_rp_read_local_oob_ext_data *rp;
6303 size_t rp_len;
6304 u16 eir_len;
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006305 u8 status, flags, role, addr[7], hash[16], rand[16];
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006306 int err;
6307
6308 BT_DBG("%s", hdev->name);
6309
6310 if (!hdev_is_powered(hdev))
6311 return mgmt_cmd_complete(sk, hdev->id,
6312 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6313 MGMT_STATUS_NOT_POWERED,
6314 &cp->type, sizeof(cp->type));
6315
6316 switch (cp->type) {
6317 case BIT(BDADDR_BREDR):
6318 status = mgmt_bredr_support(hdev);
6319 if (status)
6320 return mgmt_cmd_complete(sk, hdev->id,
6321 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6322 status, &cp->type,
6323 sizeof(cp->type));
6324 eir_len = 5;
6325 break;
6326 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
6327 status = mgmt_le_support(hdev);
6328 if (status)
6329 return mgmt_cmd_complete(sk, hdev->id,
6330 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6331 status, &cp->type,
6332 sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006333 eir_len = 9 + 3 + 18 + 18 + 3;
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006334 break;
6335 default:
6336 return mgmt_cmd_complete(sk, hdev->id,
6337 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6338 MGMT_STATUS_INVALID_PARAMS,
6339 &cp->type, sizeof(cp->type));
6340 }
6341
6342 hci_dev_lock(hdev);
6343
6344 rp_len = sizeof(*rp) + eir_len;
6345 rp = kmalloc(rp_len, GFP_ATOMIC);
6346 if (!rp) {
6347 hci_dev_unlock(hdev);
6348 return -ENOMEM;
6349 }
6350
6351 eir_len = 0;
6352 switch (cp->type) {
6353 case BIT(BDADDR_BREDR):
6354 eir_len = eir_append_data(rp->eir, eir_len, EIR_CLASS_OF_DEV,
6355 hdev->dev_class, 3);
6356 break;
6357 case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
Marcel Holtmann5082a592015-03-16 12:39:00 -07006358 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
6359 smp_generate_oob(hdev, hash, rand) < 0) {
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006360 hci_dev_unlock(hdev);
6361 err = mgmt_cmd_complete(sk, hdev->id,
Marcel Holtmann5082a592015-03-16 12:39:00 -07006362 MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
6363 MGMT_STATUS_FAILED,
6364 &cp->type, sizeof(cp->type));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006365 goto done;
6366 }
6367
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006368 if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
6369 memcpy(addr, &hdev->rpa, 6);
6370 addr[6] = 0x01;
6371 } else if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
6372 !bacmp(&hdev->bdaddr, BDADDR_ANY) ||
6373 (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
6374 bacmp(&hdev->static_addr, BDADDR_ANY))) {
6375 memcpy(addr, &hdev->static_addr, 6);
6376 addr[6] = 0x01;
6377 } else {
6378 memcpy(addr, &hdev->bdaddr, 6);
6379 addr[6] = 0x00;
6380 }
6381
6382 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
6383 addr, sizeof(addr));
6384
6385 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
6386 role = 0x02;
6387 else
6388 role = 0x01;
6389
6390 eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
6391 &role, sizeof(role));
6392
Marcel Holtmann5082a592015-03-16 12:39:00 -07006393 if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
6394 eir_len = eir_append_data(rp->eir, eir_len,
6395 EIR_LE_SC_CONFIRM,
6396 hash, sizeof(hash));
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006397
Marcel Holtmann5082a592015-03-16 12:39:00 -07006398 eir_len = eir_append_data(rp->eir, eir_len,
6399 EIR_LE_SC_RANDOM,
6400 rand, sizeof(rand));
6401 }
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006402
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006403 flags = get_adv_discov_flags(hdev);
6404
6405 if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
6406 flags |= LE_AD_NO_BREDR;
6407
6408 eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
6409 &flags, sizeof(flags));
6410 break;
6411 }
6412
6413 rp->type = cp->type;
6414 rp->eir_len = cpu_to_le16(eir_len);
6415
6416 hci_dev_unlock(hdev);
6417
Marcel Holtmann72000df2015-03-16 16:11:21 -07006418 hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
6419
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006420 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
Marcel Holtmann5425f982015-03-16 16:05:44 -07006421 MGMT_STATUS_SUCCESS, rp, sizeof(*rp) + eir_len);
Marcel Holtmann72000df2015-03-16 16:11:21 -07006422 if (err < 0)
6423 goto done;
6424
6425 err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
6426 rp, sizeof(*rp) + eir_len,
6427 HCI_MGMT_OOB_DATA_EVENTS, sk);
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006428
Marcel Holtmann0821a2c2015-03-16 01:10:23 -07006429done:
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006430 kfree(rp);
6431
6432 return err;
6433}
6434
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006435static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
6436 void *data, u16 data_len)
6437{
6438 struct mgmt_rp_read_adv_features *rp;
6439 size_t rp_len;
6440 int err;
6441
6442 BT_DBG("%s", hdev->name);
6443
6444 hci_dev_lock(hdev);
6445
6446 rp_len = sizeof(*rp);
6447 rp = kmalloc(rp_len, GFP_ATOMIC);
6448 if (!rp) {
6449 hci_dev_unlock(hdev);
6450 return -ENOMEM;
6451 }
6452
6453 rp->supported_flags = cpu_to_le32(0);
6454 rp->max_adv_data_len = 31;
6455 rp->max_scan_rsp_len = 31;
6456 rp->max_instances = 0;
6457 rp->num_instances = 0;
6458
6459 hci_dev_unlock(hdev);
6460
6461 err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
6462 MGMT_STATUS_SUCCESS, rp, rp_len);
6463
6464 kfree(rp);
6465
6466 return err;
6467}
6468
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006469static const struct hci_mgmt_handler mgmt_handlers[] = {
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006470 { NULL }, /* 0x0000 (no command) */
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006471 { read_version, MGMT_READ_VERSION_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006472 HCI_MGMT_NO_HDEV |
6473 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006474 { read_commands, MGMT_READ_COMMANDS_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006475 HCI_MGMT_NO_HDEV |
6476 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006477 { read_index_list, MGMT_READ_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006478 HCI_MGMT_NO_HDEV |
6479 HCI_MGMT_UNTRUSTED },
6480 { read_controller_info, MGMT_READ_INFO_SIZE,
6481 HCI_MGMT_UNTRUSTED },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006482 { set_powered, MGMT_SETTING_SIZE },
6483 { set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
6484 { set_connectable, MGMT_SETTING_SIZE },
6485 { set_fast_connectable, MGMT_SETTING_SIZE },
6486 { set_bondable, MGMT_SETTING_SIZE },
6487 { set_link_security, MGMT_SETTING_SIZE },
6488 { set_ssp, MGMT_SETTING_SIZE },
6489 { set_hs, MGMT_SETTING_SIZE },
6490 { set_le, MGMT_SETTING_SIZE },
6491 { set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
6492 { set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
6493 { add_uuid, MGMT_ADD_UUID_SIZE },
6494 { remove_uuid, MGMT_REMOVE_UUID_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006495 { load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
6496 HCI_MGMT_VAR_LEN },
6497 { load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
6498 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006499 { disconnect, MGMT_DISCONNECT_SIZE },
6500 { get_connections, MGMT_GET_CONNECTIONS_SIZE },
6501 { pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
6502 { pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
6503 { set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
6504 { pair_device, MGMT_PAIR_DEVICE_SIZE },
6505 { cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
6506 { unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
6507 { user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
6508 { user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
6509 { user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
6510 { user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006511 { read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
6512 { add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
6513 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006514 { remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
6515 { start_discovery, MGMT_START_DISCOVERY_SIZE },
6516 { stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
6517 { confirm_name, MGMT_CONFIRM_NAME_SIZE },
6518 { block_device, MGMT_BLOCK_DEVICE_SIZE },
6519 { unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
6520 { set_device_id, MGMT_SET_DEVICE_ID_SIZE },
6521 { set_advertising, MGMT_SETTING_SIZE },
6522 { set_bredr, MGMT_SETTING_SIZE },
6523 { set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
6524 { set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
6525 { set_secure_conn, MGMT_SETTING_SIZE },
6526 { set_debug_keys, MGMT_SETTING_SIZE },
6527 { set_privacy, MGMT_SET_PRIVACY_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006528 { load_irks, MGMT_LOAD_IRKS_SIZE,
6529 HCI_MGMT_VAR_LEN },
Marcel Holtmann7aea86162015-03-14 19:28:02 -07006530 { get_conn_info, MGMT_GET_CONN_INFO_SIZE },
6531 { get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
6532 { add_device, MGMT_ADD_DEVICE_SIZE },
6533 { remove_device, MGMT_REMOVE_DEVICE_SIZE },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006534 { load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
6535 HCI_MGMT_VAR_LEN },
6536 { read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006537 HCI_MGMT_NO_HDEV |
6538 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006539 { read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006540 HCI_MGMT_UNCONFIGURED |
6541 HCI_MGMT_UNTRUSTED },
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006542 { set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
6543 HCI_MGMT_UNCONFIGURED },
6544 { set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
6545 HCI_MGMT_UNCONFIGURED },
6546 { start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
6547 HCI_MGMT_VAR_LEN },
Marcel Holtmann4f0f1552015-03-14 22:43:19 -07006548 { read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
Marcel Holtmann96f14742015-03-14 19:27:57 -07006549 { read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
Marcel Holtmannc91041d2015-03-14 19:28:01 -07006550 HCI_MGMT_NO_HDEV |
6551 HCI_MGMT_UNTRUSTED },
Marcel Holtmannd3d53052015-03-14 20:53:25 -07006552 { read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006553};
6554
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006555int mgmt_control(struct hci_mgmt_chan *chan, struct sock *sk,
6556 struct msghdr *msg, size_t msglen)
Johan Hedberg03811012010-12-08 00:21:06 +02006557{
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006558 void *buf;
6559 u8 *cp;
Johan Hedberg03811012010-12-08 00:21:06 +02006560 struct mgmt_hdr *hdr;
Szymon Janc4e51eae2011-02-25 19:05:48 +01006561 u16 opcode, index, len;
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006562 struct hci_dev *hdev = NULL;
Johan Hedberg6d785aa32015-03-06 21:08:51 +02006563 const struct hci_mgmt_handler *handler;
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006564 bool var_len, no_hdev;
Johan Hedberg03811012010-12-08 00:21:06 +02006565 int err;
6566
6567 BT_DBG("got %zu bytes", msglen);
6568
6569 if (msglen < sizeof(*hdr))
6570 return -EINVAL;
6571
Gustavo F. Padovane63a15e2011-04-04 18:56:53 -03006572 buf = kmalloc(msglen, GFP_KERNEL);
Johan Hedberg03811012010-12-08 00:21:06 +02006573 if (!buf)
6574 return -ENOMEM;
6575
Al Viro6ce8e9c2014-04-06 21:25:44 -04006576 if (memcpy_from_msg(buf, msg, msglen)) {
Johan Hedberg03811012010-12-08 00:21:06 +02006577 err = -EFAULT;
6578 goto done;
6579 }
6580
Vinicius Costa Gomes650f7262012-02-02 21:07:59 -03006581 hdr = buf;
Marcel Holtmann1f350c82012-03-12 20:31:08 -07006582 opcode = __le16_to_cpu(hdr->opcode);
6583 index = __le16_to_cpu(hdr->index);
6584 len = __le16_to_cpu(hdr->len);
Johan Hedberg03811012010-12-08 00:21:06 +02006585
6586 if (len != msglen - sizeof(*hdr)) {
6587 err = -EINVAL;
6588 goto done;
6589 }
6590
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006591 if (opcode >= chan->handler_count ||
6592 chan->handlers[opcode].func == NULL) {
6593 BT_DBG("Unknown op %u", opcode);
Johan Hedberga69e8372015-03-06 21:08:53 +02006594 err = mgmt_cmd_status(sk, index, opcode,
6595 MGMT_STATUS_UNKNOWN_COMMAND);
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006596 goto done;
6597 }
6598
6599 handler = &chan->handlers[opcode];
6600
Marcel Holtmannc927a102015-03-14 19:28:03 -07006601 if (!hci_sock_test_flag(sk, HCI_SOCK_TRUSTED) &&
6602 !(handler->flags & HCI_MGMT_UNTRUSTED)) {
6603 err = mgmt_cmd_status(sk, index, opcode,
6604 MGMT_STATUS_PERMISSION_DENIED);
6605 goto done;
6606 }
6607
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006608 if (index != MGMT_INDEX_NONE) {
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006609 hdev = hci_dev_get(index);
6610 if (!hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006611 err = mgmt_cmd_status(sk, index, opcode,
6612 MGMT_STATUS_INVALID_INDEX);
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006613 goto done;
6614 }
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006615
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006616 if (hci_dev_test_flag(hdev, HCI_SETUP) ||
6617 hci_dev_test_flag(hdev, HCI_CONFIG) ||
6618 hci_dev_test_flag(hdev, HCI_USER_CHANNEL)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006619 err = mgmt_cmd_status(sk, index, opcode,
6620 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann0736cfa2013-08-26 21:40:51 -07006621 goto done;
6622 }
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006623
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006624 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) &&
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006625 !(handler->flags & HCI_MGMT_UNCONFIGURED)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006626 err = mgmt_cmd_status(sk, index, opcode,
6627 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann42a9bc142014-07-04 16:54:40 +02006628 goto done;
6629 }
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006630 }
6631
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006632 no_hdev = (handler->flags & HCI_MGMT_NO_HDEV);
6633 if (no_hdev != !hdev) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006634 err = mgmt_cmd_status(sk, index, opcode,
6635 MGMT_STATUS_INVALID_INDEX);
Marcel Holtmann73d1df22014-07-02 22:10:52 +02006636 goto done;
6637 }
6638
Johan Hedbergb9a245fb2015-03-06 21:08:52 +02006639 var_len = (handler->flags & HCI_MGMT_VAR_LEN);
6640 if ((var_len && len < handler->data_len) ||
6641 (!var_len && len != handler->data_len)) {
Johan Hedberga69e8372015-03-06 21:08:53 +02006642 err = mgmt_cmd_status(sk, index, opcode,
6643 MGMT_STATUS_INVALID_PARAMS);
Johan Hedbergbe22b542012-03-01 22:24:41 +02006644 goto done;
6645 }
6646
Johan Hedberg0f4e68c2012-02-28 17:18:30 +02006647 if (hdev)
6648 mgmt_init_hdev(sk, hdev);
6649
6650 cp = buf + sizeof(*hdr);
6651
Johan Hedbergbe22b542012-03-01 22:24:41 +02006652 err = handler->func(sk, hdev, cp, len);
Johan Hedberge41d8b42010-12-13 21:07:03 +02006653 if (err < 0)
6654 goto done;
6655
Johan Hedberg03811012010-12-08 00:21:06 +02006656 err = msglen;
6657
6658done:
Johan Hedbergbdb6d972012-02-28 06:13:32 +02006659 if (hdev)
6660 hci_dev_put(hdev);
6661
Johan Hedberg03811012010-12-08 00:21:06 +02006662 kfree(buf);
6663 return err;
6664}
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006665
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006666void mgmt_index_added(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006667{
Marcel Holtmannced85542015-03-14 19:27:56 -07006668 struct mgmt_ev_ext_index ev;
Andrei Emeltchenkobb4b2a92012-07-19 17:03:40 +03006669
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006670 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6671 return;
6672
Marcel Holtmannf9207332015-03-14 19:27:55 -07006673 switch (hdev->dev_type) {
6674 case HCI_BREDR:
6675 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6676 mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev,
6677 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006678 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006679 } else {
6680 mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
6681 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006682 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006683 }
6684 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006685 case HCI_AMP:
6686 ev.type = 0x02;
6687 break;
6688 default:
6689 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006690 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006691
6692 ev.bus = hdev->bus;
6693
6694 mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
6695 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006696}
6697
Marcel Holtmannbf6b56d2013-10-06 23:55:45 -07006698void mgmt_index_removed(struct hci_dev *hdev)
Johan Hedbergc71e97b2010-12-13 21:07:07 +02006699{
Marcel Holtmannced85542015-03-14 19:27:56 -07006700 struct mgmt_ev_ext_index ev;
Johan Hedberg5f159032012-03-02 03:13:19 +02006701 u8 status = MGMT_STATUS_INVALID_INDEX;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006702
Marcel Holtmann0602a8a2014-07-02 21:30:54 +02006703 if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
6704 return;
6705
Marcel Holtmannf9207332015-03-14 19:27:55 -07006706 switch (hdev->dev_type) {
6707 case HCI_BREDR:
6708 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedbergb24752f2011-11-03 14:40:33 +02006709
Marcel Holtmannf9207332015-03-14 19:27:55 -07006710 if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
6711 mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev,
6712 NULL, 0, HCI_MGMT_UNCONF_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006713 ev.type = 0x01;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006714 } else {
6715 mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
6716 HCI_MGMT_INDEX_EVENTS);
Marcel Holtmannced85542015-03-14 19:27:56 -07006717 ev.type = 0x00;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006718 }
6719 break;
Marcel Holtmannced85542015-03-14 19:27:56 -07006720 case HCI_AMP:
6721 ev.type = 0x02;
6722 break;
6723 default:
6724 return;
Marcel Holtmannf9207332015-03-14 19:27:55 -07006725 }
Marcel Holtmannced85542015-03-14 19:27:56 -07006726
6727 ev.bus = hdev->bus;
6728
6729 mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
6730 HCI_MGMT_EXT_INDEX_EVENTS);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006731}
6732
Andre Guedes6046dc32014-02-26 20:21:51 -03006733/* This function requires the caller holds hdev->lock */
Johan Hedberg2cf22212014-12-19 22:26:00 +02006734static void restart_le_actions(struct hci_request *req)
Andre Guedes6046dc32014-02-26 20:21:51 -03006735{
Johan Hedberg2cf22212014-12-19 22:26:00 +02006736 struct hci_dev *hdev = req->hdev;
Andre Guedes6046dc32014-02-26 20:21:51 -03006737 struct hci_conn_params *p;
6738
6739 list_for_each_entry(p, &hdev->le_conn_params, list) {
Johan Hedbergd7347f32014-07-04 12:37:23 +03006740 /* Needed for AUTO_OFF case where might not "really"
6741 * have been powered off.
6742 */
6743 list_del_init(&p->action);
6744
6745 switch (p->auto_connect) {
Marcel Holtmann4b9e7e72014-07-23 21:55:23 +02006746 case HCI_AUTO_CONN_DIRECT:
Johan Hedbergd7347f32014-07-04 12:37:23 +03006747 case HCI_AUTO_CONN_ALWAYS:
6748 list_add(&p->action, &hdev->pend_le_conns);
6749 break;
6750 case HCI_AUTO_CONN_REPORT:
6751 list_add(&p->action, &hdev->pend_le_reports);
6752 break;
6753 default:
6754 break;
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006755 }
Andre Guedes6046dc32014-02-26 20:21:51 -03006756 }
Marcel Holtmannc83ed192014-07-01 19:28:24 +02006757
Johan Hedberg2cf22212014-12-19 22:26:00 +02006758 __hci_update_background_scan(req);
Andre Guedes6046dc32014-02-26 20:21:51 -03006759}
6760
Marcel Holtmann1904a852015-01-11 13:50:44 -08006761static void powered_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Johan Hedberg229ab392013-03-15 17:06:53 -05006762{
6763 struct cmd_lookup match = { NULL, hdev };
6764
6765 BT_DBG("status 0x%02x", status);
6766
Marcel Holtmann162a3ba2015-01-14 15:43:11 -08006767 if (!status) {
6768 /* Register the available SMP channels (BR/EDR and LE) only
6769 * when successfully powering on the controller. This late
6770 * registration is required so that LE SMP can clearly
6771 * decide if the public address or static address is used.
6772 */
6773 smp_register(hdev);
6774 }
6775
Johan Hedberg229ab392013-03-15 17:06:53 -05006776 hci_dev_lock(hdev);
6777
6778 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
6779
6780 new_settings(hdev, match.sk);
6781
6782 hci_dev_unlock(hdev);
6783
6784 if (match.sk)
6785 sock_put(match.sk);
6786}
6787
Johan Hedberg70da6242013-03-15 17:06:51 -05006788static int powered_update_hci(struct hci_dev *hdev)
6789{
Johan Hedberg890ea892013-03-15 17:06:52 -05006790 struct hci_request req;
Johan Hedberg70da6242013-03-15 17:06:51 -05006791 u8 link_sec;
6792
Johan Hedberg890ea892013-03-15 17:06:52 -05006793 hci_req_init(&req, hdev);
6794
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006795 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED) &&
Johan Hedberg70da6242013-03-15 17:06:51 -05006796 !lmp_host_ssp_capable(hdev)) {
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006797 u8 mode = 0x01;
Johan Hedberg70da6242013-03-15 17:06:51 -05006798
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006799 hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, sizeof(mode), &mode);
Johan Hedberg70da6242013-03-15 17:06:51 -05006800
Marcel Holtmann574ea3c2015-01-22 11:15:20 -08006801 if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
6802 u8 support = 0x01;
6803
6804 hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT,
6805 sizeof(support), &support);
6806 }
Johan Hedbergec6f99b2014-12-12 13:30:11 +02006807 }
6808
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006809 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
Johan Hedbergc73eee92013-04-19 18:35:21 +03006810 lmp_bredr_capable(hdev)) {
Johan Hedberg70da6242013-03-15 17:06:51 -05006811 struct hci_cp_write_le_host_supported cp;
6812
Marcel Holtmann32226e42014-07-24 20:04:16 +02006813 cp.le = 0x01;
6814 cp.simul = 0x00;
Johan Hedberg70da6242013-03-15 17:06:51 -05006815
6816 /* Check first if we already have the right
6817 * host state (host features set)
6818 */
6819 if (cp.le != lmp_host_le_capable(hdev) ||
6820 cp.simul != lmp_host_le_br_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05006821 hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
6822 sizeof(cp), &cp);
Johan Hedberg70da6242013-03-15 17:06:51 -05006823 }
6824
Marcel Holtmannd13eafc2013-10-02 04:41:30 -07006825 if (lmp_le_capable(hdev)) {
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006826 /* Make sure the controller has a good default for
6827 * advertising data. This also applies to the case
6828 * where BR/EDR was toggled during the AUTO_OFF phase.
6829 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006830 if (hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
Marcel Holtmann5947f4b2013-10-16 00:16:50 -07006831 update_adv_data(&req);
Marcel Holtmannf14d8f62013-10-16 00:16:48 -07006832 update_scan_rsp_data(&req);
6833 }
Marcel Holtmann441ad2d2013-10-15 06:33:52 -07006834
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006835 if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmannbba3aa52013-10-06 02:55:21 -07006836 enable_advertising(&req);
Johan Hedberg2cf22212014-12-19 22:26:00 +02006837
6838 restart_le_actions(&req);
Johan Hedbergeeca6f82013-09-25 13:26:09 +03006839 }
6840
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006841 link_sec = hci_dev_test_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg70da6242013-03-15 17:06:51 -05006842 if (link_sec != test_bit(HCI_AUTH, &hdev->flags))
Johan Hedberg890ea892013-03-15 17:06:52 -05006843 hci_req_add(&req, HCI_OP_WRITE_AUTH_ENABLE,
6844 sizeof(link_sec), &link_sec);
Johan Hedberg70da6242013-03-15 17:06:51 -05006845
6846 if (lmp_bredr_capable(hdev)) {
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006847 if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
Johan Hedberg406ef2a2015-03-10 20:14:27 +02006848 write_fast_connectable(&req, true);
6849 else
6850 write_fast_connectable(&req, false);
Johan Hedberg1d2dc5b2014-12-19 13:40:19 +02006851 __hci_update_page_scan(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006852 update_class(&req);
Johan Hedberg13928972013-03-15 17:07:00 -05006853 update_name(&req);
Johan Hedberg890ea892013-03-15 17:06:52 -05006854 update_eir(&req);
Johan Hedberg70da6242013-03-15 17:06:51 -05006855 }
6856
Johan Hedberg229ab392013-03-15 17:06:53 -05006857 return hci_req_run(&req, powered_complete);
Johan Hedberg70da6242013-03-15 17:06:51 -05006858}
6859
Johan Hedberg744cf192011-11-08 20:40:14 +02006860int mgmt_powered(struct hci_dev *hdev, u8 powered)
Johan Hedberg5add6af2010-12-16 10:00:37 +02006861{
Johan Hedberg76a7f3a2012-02-17 00:34:40 +02006862 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg98459042014-12-12 11:15:21 +02006863 u8 status, zero_cod[] = { 0, 0, 0 };
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006864 int err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006865
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006866 if (!hci_dev_test_flag(hdev, HCI_MGMT))
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006867 return 0;
6868
Johan Hedberg5e5282b2012-02-21 16:01:30 +02006869 if (powered) {
Johan Hedberg229ab392013-03-15 17:06:53 -05006870 if (powered_update_hci(hdev) == 0)
6871 return 0;
Johan Hedbergfe038882013-01-16 16:15:34 +02006872
Johan Hedberg229ab392013-03-15 17:06:53 -05006873 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp,
6874 &match);
6875 goto new_settings;
Johan Hedbergb24752f2011-11-03 14:40:33 +02006876 }
6877
Johan Hedberg229ab392013-03-15 17:06:53 -05006878 mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
Johan Hedberg98459042014-12-12 11:15:21 +02006879
6880 /* If the power off is because of hdev unregistration let
6881 * use the appropriate INVALID_INDEX status. Otherwise use
6882 * NOT_POWERED. We cover both scenarios here since later in
6883 * mgmt_index_removed() any hci_conn callbacks will have already
6884 * been triggered, potentially causing misleading DISCONNECTED
6885 * status responses.
6886 */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006887 if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
Johan Hedberg98459042014-12-12 11:15:21 +02006888 status = MGMT_STATUS_INVALID_INDEX;
6889 else
6890 status = MGMT_STATUS_NOT_POWERED;
6891
6892 mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
Johan Hedberg229ab392013-03-15 17:06:53 -05006893
6894 if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07006895 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
6896 zero_cod, sizeof(zero_cod), NULL);
Johan Hedberg229ab392013-03-15 17:06:53 -05006897
6898new_settings:
Johan Hedbergbeadb2b2012-02-21 16:55:31 +02006899 err = new_settings(hdev, match.sk);
Johan Hedbergeec8d2b2010-12-16 10:17:38 +02006900
6901 if (match.sk)
6902 sock_put(match.sk);
6903
Johan Hedberg7bb895d2012-02-17 01:20:00 +02006904 return err;
Johan Hedberg5add6af2010-12-16 10:00:37 +02006905}
Johan Hedberg73f22f62010-12-29 16:00:25 +02006906
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006907void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
Johan Hedberg96570ff2013-05-29 09:51:29 +03006908{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02006909 struct mgmt_pending_cmd *cmd;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006910 u8 status;
6911
6912 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
6913 if (!cmd)
Marcel Holtmann3eec7052013-10-06 23:55:46 -07006914 return;
Johan Hedberg96570ff2013-05-29 09:51:29 +03006915
6916 if (err == -ERFKILL)
6917 status = MGMT_STATUS_RFKILLED;
6918 else
6919 status = MGMT_STATUS_FAILED;
6920
Johan Hedberga69e8372015-03-06 21:08:53 +02006921 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006922
6923 mgmt_pending_remove(cmd);
Johan Hedberg96570ff2013-05-29 09:51:29 +03006924}
6925
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006926void mgmt_discoverable_timeout(struct hci_dev *hdev)
6927{
6928 struct hci_request req;
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006929
6930 hci_dev_lock(hdev);
6931
6932 /* When discoverable timeout triggers, then just make sure
6933 * the limited discoverable flag is cleared. Even in the case
6934 * of a timeout triggered from general discoverable, it is
6935 * safe to unconditionally clear the flag.
6936 */
Marcel Holtmanna358dc12015-03-13 02:11:02 -07006937 hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
6938 hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006939
6940 hci_req_init(&req, hdev);
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07006941 if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
Johan Hedberg4b580612013-10-19 23:38:21 +03006942 u8 scan = SCAN_PAGE;
6943 hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
6944 sizeof(scan), &scan);
6945 }
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006946 update_class(&req);
Johan Hedberg9a43e252013-10-20 19:00:07 +03006947 update_adv_data(&req);
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006948 hci_req_run(&req, NULL);
6949
6950 hdev->discov_timeout = 0;
6951
Johan Hedberg9a43e252013-10-20 19:00:07 +03006952 new_settings(hdev, NULL);
6953
Marcel Holtmannd1967ff2013-10-15 10:57:40 -07006954 hci_dev_unlock(hdev);
6955}
6956
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006957void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
6958 bool persistent)
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006959{
Johan Hedberg86742e12011-11-07 23:13:38 +02006960 struct mgmt_ev_new_link_key ev;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006961
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006962 memset(&ev, 0, sizeof(ev));
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006963
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006964 ev.store_hint = persistent;
Johan Hedbergd753fdc2012-02-17 14:06:34 +02006965 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03006966 ev.key.addr.type = BDADDR_BREDR;
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006967 ev.key.type = key->type;
Andrei Emeltchenko9b3b4462012-05-23 11:31:20 +03006968 memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
Vinicius Costa Gomesa492cd52011-08-25 20:02:29 -03006969 ev.key.pin_len = key->pin_len;
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006970
Marcel Holtmanndc4a5ee2013-10-15 10:15:57 -07006971 mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +02006972}
Johan Hedbergf7520542011-01-20 12:34:39 +02006973
Johan Hedbergd7b25452014-05-23 13:19:53 +03006974static u8 mgmt_ltk_type(struct smp_ltk *ltk)
6975{
Johan Hedberg23fb8de2014-05-23 13:15:37 +03006976 switch (ltk->type) {
6977 case SMP_LTK:
6978 case SMP_LTK_SLAVE:
6979 if (ltk->authenticated)
6980 return MGMT_LTK_AUTHENTICATED;
6981 return MGMT_LTK_UNAUTHENTICATED;
6982 case SMP_LTK_P256:
6983 if (ltk->authenticated)
6984 return MGMT_LTK_P256_AUTH;
6985 return MGMT_LTK_P256_UNAUTH;
6986 case SMP_LTK_P256_DEBUG:
6987 return MGMT_LTK_P256_DEBUG;
6988 }
Johan Hedbergd7b25452014-05-23 13:19:53 +03006989
6990 return MGMT_LTK_UNAUTHENTICATED;
6991}
6992
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07006993void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03006994{
6995 struct mgmt_ev_new_long_term_key ev;
6996
6997 memset(&ev, 0, sizeof(ev));
6998
Marcel Holtmann5192d302014-02-19 17:11:58 -08006999 /* Devices using resolvable or non-resolvable random addresses
7000 * without providing an indentity resolving key don't require
7001 * to store long term keys. Their addresses will change the
7002 * next time around.
7003 *
7004 * Only when a remote device provides an identity address
7005 * make sure the long term key is stored. If the remote
7006 * identity is known, the long term keys are internally
7007 * mapped to the identity address. So allow static random
7008 * and public addresses here.
7009 */
Johan Hedbergba74b662014-02-19 14:57:45 +02007010 if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7011 (key->bdaddr.b[5] & 0xc0) != 0xc0)
7012 ev.store_hint = 0x00;
7013 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007014 ev.store_hint = persistent;
Johan Hedbergba74b662014-02-19 14:57:45 +02007015
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007016 bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007017 ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type);
Johan Hedbergd7b25452014-05-23 13:19:53 +03007018 ev.key.type = mgmt_ltk_type(key);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007019 ev.key.enc_size = key->enc_size;
7020 ev.key.ediv = key->ediv;
Marcel Holtmannfe39c7b2014-02-27 16:00:28 -08007021 ev.key.rand = key->rand;
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007022
Johan Hedberg2ceba532014-06-16 19:25:16 +03007023 if (key->type == SMP_LTK)
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007024 ev.key.master = 1;
7025
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007026 memcpy(ev.key.val, key->val, sizeof(key->val));
7027
Marcel Holtmann083368f2013-10-15 14:26:29 -07007028 mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
Vinicius Costa Gomes346af672012-02-02 21:08:02 -03007029}
7030
Johan Hedberg95fbac82014-02-19 15:18:31 +02007031void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk)
7032{
7033 struct mgmt_ev_new_irk ev;
7034
7035 memset(&ev, 0, sizeof(ev));
7036
Marcel Holtmannbab6d1e2014-02-19 11:51:54 -08007037 /* For identity resolving keys from devices that are already
7038 * using a public address or static random address, do not
7039 * ask for storing this key. The identity resolving key really
7040 * is only mandatory for devices using resovlable random
7041 * addresses.
7042 *
7043 * Storing all identity resolving keys has the downside that
7044 * they will be also loaded on next boot of they system. More
7045 * identity resolving keys, means more time during scanning is
7046 * needed to actually resolve these addresses.
7047 */
7048 if (bacmp(&irk->rpa, BDADDR_ANY))
7049 ev.store_hint = 0x01;
7050 else
7051 ev.store_hint = 0x00;
7052
Johan Hedberg95fbac82014-02-19 15:18:31 +02007053 bacpy(&ev.rpa, &irk->rpa);
7054 bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
7055 ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type);
7056 memcpy(ev.irk.val, irk->val, sizeof(irk->val));
7057
7058 mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
7059}
7060
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007061void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
7062 bool persistent)
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007063{
7064 struct mgmt_ev_new_csrk ev;
7065
7066 memset(&ev, 0, sizeof(ev));
7067
7068 /* Devices using resolvable or non-resolvable random addresses
7069 * without providing an indentity resolving key don't require
7070 * to store signature resolving keys. Their addresses will change
7071 * the next time around.
7072 *
7073 * Only when a remote device provides an identity address
7074 * make sure the signature resolving key is stored. So allow
7075 * static random and public addresses here.
7076 */
7077 if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
7078 (csrk->bdaddr.b[5] & 0xc0) != 0xc0)
7079 ev.store_hint = 0x00;
7080 else
Marcel Holtmann53ac6ab2014-03-09 23:38:42 -07007081 ev.store_hint = persistent;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007082
7083 bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
7084 ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type);
Johan Hedberg4cd39282015-02-27 10:11:13 +02007085 ev.key.type = csrk->type;
Marcel Holtmann7ee4ea32014-03-09 12:19:17 -07007086 memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
7087
7088 mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
7089}
7090
Andre Guedesffb5a8272014-07-01 18:10:11 -03007091void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedbergf4869e22014-07-02 17:37:32 +03007092 u8 bdaddr_type, u8 store_hint, u16 min_interval,
7093 u16 max_interval, u16 latency, u16 timeout)
Andre Guedesffb5a8272014-07-01 18:10:11 -03007094{
7095 struct mgmt_ev_new_conn_param ev;
7096
Johan Hedbergc103aea2014-07-02 17:37:34 +03007097 if (!hci_is_identity_address(bdaddr, bdaddr_type))
7098 return;
7099
Andre Guedesffb5a8272014-07-01 18:10:11 -03007100 memset(&ev, 0, sizeof(ev));
7101 bacpy(&ev.addr.bdaddr, bdaddr);
7102 ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
Johan Hedbergf4869e22014-07-02 17:37:32 +03007103 ev.store_hint = store_hint;
Andre Guedesffb5a8272014-07-01 18:10:11 -03007104 ev.min_interval = cpu_to_le16(min_interval);
7105 ev.max_interval = cpu_to_le16(max_interval);
7106 ev.latency = cpu_to_le16(latency);
7107 ev.timeout = cpu_to_le16(timeout);
7108
7109 mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
7110}
7111
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007112void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
7113 u32 flags, u8 *name, u8 name_len)
Johan Hedbergf7520542011-01-20 12:34:39 +02007114{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007115 char buf[512];
7116 struct mgmt_ev_device_connected *ev = (void *) buf;
7117 u16 eir_len = 0;
Johan Hedbergf7520542011-01-20 12:34:39 +02007118
Alfonso Acosta48ec92f2014-10-07 08:44:10 +00007119 bacpy(&ev->addr.bdaddr, &conn->dst);
7120 ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
Johan Hedbergf7520542011-01-20 12:34:39 +02007121
Johan Hedbergc95f0ba2012-02-23 22:54:38 +02007122 ev->flags = __cpu_to_le32(flags);
Johan Hedberg08c79b62012-02-23 22:31:51 +02007123
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007124 /* We must ensure that the EIR Data fields are ordered and
7125 * unique. Keep it simple for now and avoid the problem by not
7126 * adding any BR/EDR data to the LE adv.
7127 */
7128 if (conn->le_adv_data_len > 0) {
7129 memcpy(&ev->eir[eir_len],
7130 conn->le_adv_data, conn->le_adv_data_len);
7131 eir_len = conn->le_adv_data_len;
7132 } else {
7133 if (name_len > 0)
7134 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
7135 name, name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007136
Alfonso Acostaddbea5c2014-10-07 08:44:12 +00007137 if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
Alfonso Acostafd45ada2014-10-07 08:44:11 +00007138 eir_len = eir_append_data(ev->eir, eir_len,
7139 EIR_CLASS_OF_DEV,
7140 conn->dev_class, 3);
7141 }
Johan Hedbergb644ba32012-01-17 21:48:47 +02007142
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007143 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007144
Marcel Holtmannecd90ae2013-10-06 23:55:49 -07007145 mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf,
7146 sizeof(*ev) + eir_len, NULL);
Johan Hedbergf7520542011-01-20 12:34:39 +02007147}
7148
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007149static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007150{
Johan Hedberg8962ee72011-01-20 12:40:27 +02007151 struct sock **sk = data;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007152
Johan Hedbergf5818c22014-12-05 13:36:02 +02007153 cmd->cmd_complete(cmd, 0);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007154
7155 *sk = cmd->sk;
7156 sock_hold(*sk);
7157
Johan Hedberga664b5b2011-02-19 12:06:02 -03007158 mgmt_pending_remove(cmd);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007159}
7160
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007161static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberga8a1d192011-11-10 15:54:38 +02007162{
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007163 struct hci_dev *hdev = data;
Johan Hedberg124f6e32012-02-09 13:50:12 +02007164 struct mgmt_cp_unpair_device *cp = cmd->param;
Johan Hedberga8a1d192011-11-10 15:54:38 +02007165
Johan Hedbergb1078ad2012-02-09 17:21:16 +02007166 device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
7167
Johan Hedbergd8b7b1e2014-12-05 13:36:05 +02007168 cmd->cmd_complete(cmd, 0);
Johan Hedberga8a1d192011-11-10 15:54:38 +02007169 mgmt_pending_remove(cmd);
7170}
7171
Johan Hedberg84c61d92014-08-01 11:13:30 +03007172bool mgmt_powering_down(struct hci_dev *hdev)
7173{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007174 struct mgmt_pending_cmd *cmd;
Johan Hedberg84c61d92014-08-01 11:13:30 +03007175 struct mgmt_mode *cp;
7176
7177 cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev);
7178 if (!cmd)
7179 return false;
7180
7181 cp = cmd->param;
7182 if (!cp->val)
7183 return true;
7184
7185 return false;
7186}
7187
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007188void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007189 u8 link_type, u8 addr_type, u8 reason,
7190 bool mgmt_connected)
Johan Hedbergf7520542011-01-20 12:34:39 +02007191{
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007192 struct mgmt_ev_device_disconnected ev;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007193 struct sock *sk = NULL;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007194
Johan Hedberg84c61d92014-08-01 11:13:30 +03007195 /* The connection is still in hci_conn_hash so test for 1
7196 * instead of 0 to know if this is the last one.
7197 */
7198 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7199 cancel_delayed_work(&hdev->power_off);
7200 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedberg8b064a32014-02-24 14:52:22 +02007201 }
7202
Johan Hedberg12d4a3b2014-02-24 14:52:18 +02007203 if (!mgmt_connected)
7204 return;
7205
Andre Guedes57eb7762013-10-30 19:01:41 -03007206 if (link_type != ACL_LINK && link_type != LE_LINK)
7207 return;
7208
Johan Hedberg744cf192011-11-08 20:40:14 +02007209 mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
Johan Hedbergf7520542011-01-20 12:34:39 +02007210
Mikel Astizf0d6a0e2012-08-09 09:52:30 +02007211 bacpy(&ev.addr.bdaddr, bdaddr);
7212 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7213 ev.reason = reason;
Johan Hedbergf7520542011-01-20 12:34:39 +02007214
Marcel Holtmann9b80ec52013-10-06 23:55:50 -07007215 mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007216
7217 if (sk)
Szymon Jancd97dcb62012-03-16 16:02:56 +01007218 sock_put(sk);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007219
Johan Hedberg124f6e32012-02-09 13:50:12 +02007220 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007221 hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007222}
7223
Marcel Holtmann78929242013-10-06 23:55:47 -07007224void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
7225 u8 link_type, u8 addr_type, u8 status)
Johan Hedberg8962ee72011-01-20 12:40:27 +02007226{
Andre Guedes3655bba2013-10-30 19:01:40 -03007227 u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
7228 struct mgmt_cp_disconnect *cp;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007229 struct mgmt_pending_cmd *cmd;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007230
Jefferson Delfes36a75f12012-09-18 13:36:54 -04007231 mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
7232 hdev);
7233
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007234 cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev);
Johan Hedberg8962ee72011-01-20 12:40:27 +02007235 if (!cmd)
Marcel Holtmann78929242013-10-06 23:55:47 -07007236 return;
Johan Hedberg8962ee72011-01-20 12:40:27 +02007237
Andre Guedes3655bba2013-10-30 19:01:40 -03007238 cp = cmd->param;
7239
7240 if (bacmp(bdaddr, &cp->addr.bdaddr))
7241 return;
7242
7243 if (cp->addr.type != bdaddr_type)
7244 return;
7245
Johan Hedbergf5818c22014-12-05 13:36:02 +02007246 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007247 mgmt_pending_remove(cmd);
Johan Hedbergf7520542011-01-20 12:34:39 +02007248}
Johan Hedberg17d5c042011-01-22 06:09:08 +02007249
Marcel Holtmann445608d2013-10-06 23:55:48 -07007250void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7251 u8 addr_type, u8 status)
Johan Hedberg17d5c042011-01-22 06:09:08 +02007252{
7253 struct mgmt_ev_connect_failed ev;
Johan Hedbergc9910d02014-02-27 14:35:12 +02007254
Johan Hedberg84c61d92014-08-01 11:13:30 +03007255 /* The connection is still in hci_conn_hash so test for 1
7256 * instead of 0 to know if this is the last one.
7257 */
7258 if (mgmt_powering_down(hdev) && hci_conn_count(hdev) == 1) {
7259 cancel_delayed_work(&hdev->power_off);
7260 queue_work(hdev->req_workqueue, &hdev->power_off.work);
Johan Hedbergc9910d02014-02-27 14:35:12 +02007261 }
Johan Hedberg17d5c042011-01-22 06:09:08 +02007262
Johan Hedberg4c659c32011-11-07 23:13:39 +02007263 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007264 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergca69b792011-11-11 18:10:00 +02007265 ev.status = mgmt_status(status);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007266
Marcel Holtmann445608d2013-10-06 23:55:48 -07007267 mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg17d5c042011-01-22 06:09:08 +02007268}
Johan Hedberg980e1a52011-01-22 06:10:07 +02007269
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007270void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007271{
7272 struct mgmt_ev_pin_code_request ev;
7273
Johan Hedbergd8457692012-02-17 14:24:57 +02007274 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes591f47f2012-04-24 21:02:49 -03007275 ev.addr.type = BDADDR_BREDR;
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +02007276 ev.secure = secure;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007277
Marcel Holtmannce0e4a02013-10-15 14:26:20 -07007278 mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007279}
7280
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007281void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7282 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007283{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007284 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007285
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007286 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007287 if (!cmd)
Marcel Holtmanne669cf82013-10-15 14:26:21 -07007288 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007289
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007290 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007291 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007292}
7293
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007294void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
7295 u8 status)
Johan Hedberg980e1a52011-01-22 06:10:07 +02007296{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007297 struct mgmt_pending_cmd *cmd;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007298
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007299 cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007300 if (!cmd)
Marcel Holtmann3eb38522013-10-15 14:26:22 -07007301 return;
Johan Hedberg980e1a52011-01-22 06:10:07 +02007302
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007303 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007304 mgmt_pending_remove(cmd);
Johan Hedberg980e1a52011-01-22 06:10:07 +02007305}
Johan Hedberga5c29682011-02-19 12:05:57 -03007306
Johan Hedberg744cf192011-11-08 20:40:14 +02007307int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Johan Hedberg39adbff2014-03-20 08:18:14 +02007308 u8 link_type, u8 addr_type, u32 value,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007309 u8 confirm_hint)
Johan Hedberga5c29682011-02-19 12:05:57 -03007310{
7311 struct mgmt_ev_user_confirm_request ev;
7312
Johan Hedberg744cf192011-11-08 20:40:14 +02007313 BT_DBG("%s", hdev->name);
Johan Hedberga5c29682011-02-19 12:05:57 -03007314
Johan Hedberg272d90d2012-02-09 15:26:12 +02007315 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007316 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberg55bc1a32011-04-28 11:28:56 -07007317 ev.confirm_hint = confirm_hint;
Johan Hedberg39adbff2014-03-20 08:18:14 +02007318 ev.value = cpu_to_le32(value);
Johan Hedberga5c29682011-02-19 12:05:57 -03007319
Johan Hedberg744cf192011-11-08 20:40:14 +02007320 return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007321 NULL);
Johan Hedberga5c29682011-02-19 12:05:57 -03007322}
7323
Johan Hedberg272d90d2012-02-09 15:26:12 +02007324int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007325 u8 link_type, u8 addr_type)
Brian Gix604086b2011-11-23 08:28:33 -08007326{
7327 struct mgmt_ev_user_passkey_request ev;
7328
7329 BT_DBG("%s", hdev->name);
7330
Johan Hedberg272d90d2012-02-09 15:26:12 +02007331 bacpy(&ev.addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007332 ev.addr.type = link_to_bdaddr(link_type, addr_type);
Brian Gix604086b2011-11-23 08:28:33 -08007333
7334 return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007335 NULL);
Brian Gix604086b2011-11-23 08:28:33 -08007336}
7337
Brian Gix0df4c182011-11-16 13:53:13 -08007338static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo Padovan8ce8e2b2012-05-17 00:36:20 -03007339 u8 link_type, u8 addr_type, u8 status,
7340 u8 opcode)
Johan Hedberga5c29682011-02-19 12:05:57 -03007341{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007342 struct mgmt_pending_cmd *cmd;
Johan Hedberga5c29682011-02-19 12:05:57 -03007343
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007344 cmd = mgmt_pending_find(opcode, hdev);
Johan Hedberga5c29682011-02-19 12:05:57 -03007345 if (!cmd)
7346 return -ENOENT;
7347
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007348 cmd->cmd_complete(cmd, mgmt_status(status));
Johan Hedberga664b5b2011-02-19 12:06:02 -03007349 mgmt_pending_remove(cmd);
Johan Hedberga5c29682011-02-19 12:05:57 -03007350
Johan Hedberg7776d1d2014-12-05 13:36:03 +02007351 return 0;
Johan Hedberga5c29682011-02-19 12:05:57 -03007352}
7353
Johan Hedberg744cf192011-11-08 20:40:14 +02007354int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007355 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007356{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007357 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007358 status, MGMT_OP_USER_CONFIRM_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007359}
7360
Johan Hedberg272d90d2012-02-09 15:26:12 +02007361int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007362 u8 link_type, u8 addr_type, u8 status)
Johan Hedberga5c29682011-02-19 12:05:57 -03007363{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007364 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007365 status,
7366 MGMT_OP_USER_CONFIRM_NEG_REPLY);
Johan Hedberga5c29682011-02-19 12:05:57 -03007367}
Johan Hedberg2a611692011-02-19 12:06:00 -03007368
Brian Gix604086b2011-11-23 08:28:33 -08007369int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007370 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007371{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007372 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007373 status, MGMT_OP_USER_PASSKEY_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007374}
7375
Johan Hedberg272d90d2012-02-09 15:26:12 +02007376int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007377 u8 link_type, u8 addr_type, u8 status)
Brian Gix604086b2011-11-23 08:28:33 -08007378{
Johan Hedberg272d90d2012-02-09 15:26:12 +02007379 return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
Gustavo Padovan8fc9ced2012-05-23 04:04:21 -03007380 status,
7381 MGMT_OP_USER_PASSKEY_NEG_REPLY);
Brian Gix604086b2011-11-23 08:28:33 -08007382}
7383
Johan Hedberg92a25252012-09-06 18:39:26 +03007384int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
7385 u8 link_type, u8 addr_type, u32 passkey,
7386 u8 entered)
7387{
7388 struct mgmt_ev_passkey_notify ev;
7389
7390 BT_DBG("%s", hdev->name);
7391
7392 bacpy(&ev.addr.bdaddr, bdaddr);
7393 ev.addr.type = link_to_bdaddr(link_type, addr_type);
7394 ev.passkey = __cpu_to_le32(passkey);
7395 ev.entered = entered;
7396
7397 return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
7398}
7399
Johan Hedberge1e930f2014-09-08 17:09:49 -07007400void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
Johan Hedberg2a611692011-02-19 12:06:00 -03007401{
7402 struct mgmt_ev_auth_failed ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007403 struct mgmt_pending_cmd *cmd;
Johan Hedberge1e930f2014-09-08 17:09:49 -07007404 u8 status = mgmt_status(hci_status);
Johan Hedberg2a611692011-02-19 12:06:00 -03007405
Johan Hedberge1e930f2014-09-08 17:09:49 -07007406 bacpy(&ev.addr.bdaddr, &conn->dst);
7407 ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
7408 ev.status = status;
Johan Hedberg2a611692011-02-19 12:06:00 -03007409
Johan Hedberge1e930f2014-09-08 17:09:49 -07007410 cmd = find_pairing(conn);
7411
7412 mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
7413 cmd ? cmd->sk : NULL);
7414
Johan Hedberga511b352014-12-11 21:45:45 +02007415 if (cmd) {
7416 cmd->cmd_complete(cmd, status);
7417 mgmt_pending_remove(cmd);
7418 }
Johan Hedberg2a611692011-02-19 12:06:00 -03007419}
Johan Hedbergb312b1612011-03-16 14:29:37 +02007420
Marcel Holtmann464996a2013-10-15 14:26:24 -07007421void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007422{
7423 struct cmd_lookup match = { NULL, hdev };
Marcel Holtmann464996a2013-10-15 14:26:24 -07007424 bool changed;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007425
7426 if (status) {
7427 u8 mgmt_err = mgmt_status(status);
7428 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007429 cmd_status_rsp, &mgmt_err);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007430 return;
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007431 }
7432
Marcel Holtmann464996a2013-10-15 14:26:24 -07007433 if (test_bit(HCI_AUTH, &hdev->flags))
Marcel Holtmann238be782015-03-13 02:11:06 -07007434 changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
Marcel Holtmann464996a2013-10-15 14:26:24 -07007435 else
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007436 changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
Johan Hedberg47990ea2012-02-22 11:58:37 +02007437
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007438 mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007439 &match);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007440
Johan Hedberg47990ea2012-02-22 11:58:37 +02007441 if (changed)
Marcel Holtmann464996a2013-10-15 14:26:24 -07007442 new_settings(hdev, match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007443
7444 if (match.sk)
7445 sock_put(match.sk);
Johan Hedberg33ef95e2012-02-16 23:56:27 +02007446}
7447
Johan Hedberg890ea892013-03-15 17:06:52 -05007448static void clear_eir(struct hci_request *req)
Johan Hedbergcacaf522012-02-21 00:52:42 +02007449{
Johan Hedberg890ea892013-03-15 17:06:52 -05007450 struct hci_dev *hdev = req->hdev;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007451 struct hci_cp_write_eir cp;
7452
Johan Hedberg976eb202012-10-24 21:12:01 +03007453 if (!lmp_ext_inq_capable(hdev))
Johan Hedberg890ea892013-03-15 17:06:52 -05007454 return;
Johan Hedbergcacaf522012-02-21 00:52:42 +02007455
Johan Hedbergc80da272012-02-22 15:38:48 +02007456 memset(hdev->eir, 0, sizeof(hdev->eir));
7457
Johan Hedbergcacaf522012-02-21 00:52:42 +02007458 memset(&cp, 0, sizeof(cp));
7459
Johan Hedberg890ea892013-03-15 17:06:52 -05007460 hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
Johan Hedbergcacaf522012-02-21 00:52:42 +02007461}
7462
Marcel Holtmann3e248562013-10-15 14:26:25 -07007463void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007464{
7465 struct cmd_lookup match = { NULL, hdev };
Johan Hedberg890ea892013-03-15 17:06:52 -05007466 struct hci_request req;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007467 bool changed = false;
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007468
7469 if (status) {
7470 u8 mgmt_err = mgmt_status(status);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007471
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007472 if (enable && hci_dev_test_and_clear_flag(hdev,
7473 HCI_SSP_ENABLED)) {
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007474 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007475 new_settings(hdev, NULL);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007476 }
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007477
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007478 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
7479 &mgmt_err);
Marcel Holtmann3e248562013-10-15 14:26:25 -07007480 return;
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007481 }
7482
7483 if (enable) {
Marcel Holtmann238be782015-03-13 02:11:06 -07007484 changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007485 } else {
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007486 changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007487 if (!changed)
Marcel Holtmanna69d8922015-03-13 02:11:05 -07007488 changed = hci_dev_test_and_clear_flag(hdev,
7489 HCI_HS_ENABLED);
Marcel Holtmann9ecb3e22013-10-10 03:08:11 -07007490 else
Marcel Holtmanna358dc12015-03-13 02:11:02 -07007491 hci_dev_clear_flag(hdev, HCI_HS_ENABLED);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007492 }
7493
7494 mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
7495
Johan Hedbergc0ecddc2012-02-22 12:38:31 +02007496 if (changed)
Marcel Holtmann3e248562013-10-15 14:26:25 -07007497 new_settings(hdev, match.sk);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007498
Johan Hedberg5fc6ebb2012-02-22 15:10:59 +02007499 if (match.sk)
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007500 sock_put(match.sk);
7501
Johan Hedberg890ea892013-03-15 17:06:52 -05007502 hci_req_init(&req, hdev);
7503
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007504 if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
7505 if (hci_dev_test_flag(hdev, HCI_USE_DEBUG_KEYS))
Johan Hedberg37699722014-06-24 14:00:27 +03007506 hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE,
7507 sizeof(enable), &enable);
Johan Hedberg890ea892013-03-15 17:06:52 -05007508 update_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007509 } else {
Johan Hedberg890ea892013-03-15 17:06:52 -05007510 clear_eir(&req);
Johan Hedberg37699722014-06-24 14:00:27 +03007511 }
Johan Hedberg890ea892013-03-15 17:06:52 -05007512
7513 hci_req_run(&req, NULL);
Johan Hedberged2c4ee2012-02-17 00:56:28 +02007514}
7515
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007516static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
Johan Hedberg90e70452012-02-23 23:09:40 +02007517{
7518 struct cmd_lookup *match = data;
7519
Johan Hedberg90e70452012-02-23 23:09:40 +02007520 if (match->sk == NULL) {
7521 match->sk = cmd->sk;
7522 sock_hold(match->sk);
7523 }
Johan Hedberg90e70452012-02-23 23:09:40 +02007524}
7525
Marcel Holtmann4e1b0242013-10-15 14:26:26 -07007526void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
7527 u8 status)
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007528{
Johan Hedberg90e70452012-02-23 23:09:40 +02007529 struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007530
Johan Hedberg92da6092013-03-15 17:06:55 -05007531 mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
7532 mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
7533 mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
Johan Hedberg90e70452012-02-23 23:09:40 +02007534
7535 if (!status)
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007536 mgmt_generic_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
7537 dev_class, 3, NULL);
Johan Hedberg90e70452012-02-23 23:09:40 +02007538
7539 if (match.sk)
7540 sock_put(match.sk);
Marcel Holtmann7f9a9032012-02-22 18:38:01 +01007541}
7542
Marcel Holtmann7667da32013-10-15 14:26:27 -07007543void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
Johan Hedbergb312b1612011-03-16 14:29:37 +02007544{
Johan Hedbergb312b1612011-03-16 14:29:37 +02007545 struct mgmt_cp_set_local_name ev;
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007546 struct mgmt_pending_cmd *cmd;
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007547
Johan Hedberg13928972013-03-15 17:07:00 -05007548 if (status)
Marcel Holtmann7667da32013-10-15 14:26:27 -07007549 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007550
7551 memset(&ev, 0, sizeof(ev));
7552 memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
Johan Hedberg28cc7bd2012-02-22 21:06:55 +02007553 memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007554
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007555 cmd = mgmt_pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
Johan Hedberg13928972013-03-15 17:07:00 -05007556 if (!cmd) {
7557 memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
Johan Hedbergb312b1612011-03-16 14:29:37 +02007558
Johan Hedberg13928972013-03-15 17:07:00 -05007559 /* If this is a HCI command related to powering on the
7560 * HCI dev don't send any mgmt signals.
7561 */
7562 if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
Marcel Holtmann7667da32013-10-15 14:26:27 -07007563 return;
Johan Hedbergb312b1612011-03-16 14:29:37 +02007564 }
7565
Marcel Holtmannf6b77122015-03-14 19:28:05 -07007566 mgmt_generic_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
7567 cmd ? cmd->sk : NULL);
Johan Hedbergb312b1612011-03-16 14:29:37 +02007568}
Szymon Jancc35938b2011-03-22 13:12:21 +01007569
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007570void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
Johan Hedberg38da1702014-11-17 20:52:20 +02007571 u8 *rand192, u8 *hash256, u8 *rand256,
7572 u8 status)
Szymon Jancc35938b2011-03-22 13:12:21 +01007573{
Johan Hedberg3b0602c2015-03-06 21:08:55 +02007574 struct mgmt_pending_cmd *cmd;
Szymon Jancc35938b2011-03-22 13:12:21 +01007575
Johan Hedberg744cf192011-11-08 20:40:14 +02007576 BT_DBG("%s status %u", hdev->name, status);
Szymon Jancc35938b2011-03-22 13:12:21 +01007577
Johan Hedberg2e58ef32011-11-08 20:40:15 +02007578 cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
Szymon Jancc35938b2011-03-22 13:12:21 +01007579 if (!cmd)
Marcel Holtmann3edaf092013-10-15 14:26:28 -07007580 return;
Szymon Jancc35938b2011-03-22 13:12:21 +01007581
7582 if (status) {
Johan Hedberga69e8372015-03-06 21:08:53 +02007583 mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
7584 mgmt_status(status));
Szymon Jancc35938b2011-03-22 13:12:21 +01007585 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007586 struct mgmt_rp_read_local_oob_data rp;
7587 size_t rp_size = sizeof(rp);
7588
7589 memcpy(rp.hash192, hash192, sizeof(rp.hash192));
7590 memcpy(rp.rand192, rand192, sizeof(rp.rand192));
7591
Johan Hedberg710f11c2014-05-26 11:21:22 +03007592 if (bredr_sc_enabled(hdev) && hash256 && rand256) {
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007593 memcpy(rp.hash256, hash256, sizeof(rp.hash256));
Johan Hedberg38da1702014-11-17 20:52:20 +02007594 memcpy(rp.rand256, rand256, sizeof(rp.rand256));
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007595 } else {
Johan Hedberg66f096f2015-02-02 13:23:42 +02007596 rp_size -= sizeof(rp.hash256) + sizeof(rp.rand256);
Marcel Holtmann4d2d2792014-01-10 02:07:26 -08007597 }
Johan Hedberg66f096f2015-02-02 13:23:42 +02007598
Johan Hedberg2a1afb52015-03-06 21:08:54 +02007599 mgmt_cmd_complete(cmd->sk, hdev->id,
7600 MGMT_OP_READ_LOCAL_OOB_DATA, 0,
7601 &rp, rp_size);
Szymon Jancc35938b2011-03-22 13:12:21 +01007602 }
7603
7604 mgmt_pending_remove(cmd);
Szymon Jancc35938b2011-03-22 13:12:21 +01007605}
Johan Hedberge17acd42011-03-30 23:57:16 +03007606
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007607static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
7608{
7609 int i;
7610
7611 for (i = 0; i < uuid_count; i++) {
7612 if (!memcmp(uuid, uuids[i], 16))
7613 return true;
7614 }
7615
7616 return false;
7617}
7618
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007619static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
7620{
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007621 u16 parsed = 0;
7622
7623 while (parsed < eir_len) {
7624 u8 field_len = eir[0];
7625 u8 uuid[16];
7626 int i;
7627
7628 if (field_len == 0)
7629 break;
7630
7631 if (eir_len - parsed < field_len + 1)
7632 break;
7633
7634 switch (eir[1]) {
7635 case EIR_UUID16_ALL:
7636 case EIR_UUID16_SOME:
7637 for (i = 0; i + 3 <= field_len; i += 2) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007638 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007639 uuid[13] = eir[i + 3];
7640 uuid[12] = eir[i + 2];
7641 if (has_uuid(uuid, uuid_count, uuids))
7642 return true;
7643 }
7644 break;
7645 case EIR_UUID32_ALL:
7646 case EIR_UUID32_SOME:
7647 for (i = 0; i + 5 <= field_len; i += 4) {
Johan Hedberg189f6ad2014-12-05 13:40:01 +02007648 memcpy(uuid, bluetooth_base_uuid, 16);
Jakub Pawlowski799ce932014-12-05 10:55:58 +01007649 uuid[15] = eir[i + 5];
7650 uuid[14] = eir[i + 4];
7651 uuid[13] = eir[i + 3];
7652 uuid[12] = eir[i + 2];
7653 if (has_uuid(uuid, uuid_count, uuids))
7654 return true;
7655 }
7656 break;
7657 case EIR_UUID128_ALL:
7658 case EIR_UUID128_SOME:
7659 for (i = 0; i + 17 <= field_len; i += 16) {
7660 memcpy(uuid, eir + i + 2, 16);
7661 if (has_uuid(uuid, uuid_count, uuids))
7662 return true;
7663 }
7664 break;
7665 }
7666
7667 parsed += field_len + 1;
7668 eir += field_len + 1;
7669 }
7670
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007671 return false;
7672}
7673
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007674static void restart_le_scan(struct hci_dev *hdev)
7675{
7676 /* If controller is not scanning we are done. */
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007677 if (!hci_dev_test_flag(hdev, HCI_LE_SCAN))
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007678 return;
7679
7680 if (time_after(jiffies + DISCOV_LE_RESTART_DELAY,
7681 hdev->discovery.scan_start +
7682 hdev->discovery.scan_duration))
7683 return;
7684
7685 queue_delayed_work(hdev->workqueue, &hdev->le_scan_restart,
7686 DISCOV_LE_RESTART_DELAY);
7687}
7688
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007689static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
7690 u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
7691{
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007692 /* If a RSSI threshold has been specified, and
7693 * HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
7694 * a RSSI smaller than the RSSI threshold will be dropped. If the quirk
7695 * is set, let it through for further processing, as we might need to
7696 * restart the scan.
7697 *
7698 * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
7699 * the results are also dropped.
7700 */
7701 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7702 (rssi == HCI_RSSI_INVALID ||
7703 (rssi < hdev->discovery.rssi &&
7704 !test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
7705 return false;
7706
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007707 if (hdev->discovery.uuid_count != 0) {
7708 /* If a list of UUIDs is provided in filter, results with no
7709 * matching UUID should be dropped.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007710 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007711 if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
7712 hdev->discovery.uuids) &&
7713 !eir_has_uuids(scan_rsp, scan_rsp_len,
7714 hdev->discovery.uuid_count,
7715 hdev->discovery.uuids))
7716 return false;
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007717 }
7718
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007719 /* If duplicate filtering does not report RSSI changes, then restart
7720 * scanning to ensure updated result with updated RSSI values.
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007721 */
Jakub Pawlowski2976cde2015-03-04 16:24:25 -08007722 if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
7723 restart_le_scan(hdev);
7724
7725 /* Validate RSSI value against the RSSI threshold once more. */
7726 if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
7727 rssi < hdev->discovery.rssi)
7728 return false;
7729 }
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007730
7731 return true;
7732}
7733
Marcel Holtmann901801b2013-10-06 23:55:51 -07007734void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
Marcel Holtmannaf589252014-07-01 14:11:20 +02007735 u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
7736 u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
Johan Hedberge17acd42011-03-30 23:57:16 +03007737{
Johan Hedberge319d2e2012-01-15 19:51:59 +02007738 char buf[512];
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007739 struct mgmt_ev_device_found *ev = (void *)buf;
Johan Hedberg1dc06092012-01-15 21:01:23 +02007740 size_t ev_size;
Johan Hedberge17acd42011-03-30 23:57:16 +03007741
Johan Hedberg75ce2082014-07-02 22:42:01 +03007742 /* Don't send events for a non-kernel initiated discovery. With
7743 * LE one exception is if we have pend_le_reports > 0 in which
7744 * case we're doing passive scanning and want these events.
7745 */
7746 if (!hci_discovery_active(hdev)) {
7747 if (link_type == ACL_LINK)
7748 return;
Johan Hedberg66f84552014-07-04 12:37:18 +03007749 if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports))
Johan Hedberg75ce2082014-07-02 22:42:01 +03007750 return;
7751 }
Andre Guedes12602d02013-04-30 15:29:40 -03007752
Jakub Pawlowski82f8b652015-03-04 16:24:26 -08007753 if (hdev->discovery.result_filtering) {
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007754 /* We are using service discovery */
7755 if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
7756 scan_rsp_len))
7757 return;
7758 }
Marcel Holtmannbda157a2014-12-05 10:55:56 +01007759
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007760 /* Make sure that the buffer is big enough. The 5 extra bytes
7761 * are for the potential CoD field.
7762 */
7763 if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf))
Marcel Holtmann901801b2013-10-06 23:55:51 -07007764 return;
Andre Guedes7d262f82012-01-10 18:20:49 -03007765
Johan Hedberg1dc06092012-01-15 21:01:23 +02007766 memset(buf, 0, sizeof(buf));
7767
Marcel Holtmannda25cf62014-12-05 13:03:35 +01007768 /* In case of device discovery with BR/EDR devices (pre 1.2), the
7769 * RSSI value was reported as 0 when not available. This behavior
7770 * is kept when using device discovery. This is required for full
7771 * backwards compatibility with the API.
7772 *
7773 * However when using service discovery, the value 127 will be
7774 * returned when the RSSI is not available.
7775 */
Szymon Janc91200e92015-01-22 16:57:05 +01007776 if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
7777 link_type == ACL_LINK)
Marcel Holtmannefb25132014-12-05 13:03:34 +01007778 rssi = 0;
7779
Johan Hedberg841c5642014-07-07 12:45:54 +03007780 bacpy(&ev->addr.bdaddr, bdaddr);
7781 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedberge319d2e2012-01-15 19:51:59 +02007782 ev->rssi = rssi;
Marcel Holtmannaf589252014-07-01 14:11:20 +02007783 ev->flags = cpu_to_le32(flags);
Johan Hedberge17acd42011-03-30 23:57:16 +03007784
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007785 if (eir_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007786 /* Copy EIR or advertising data into event */
Johan Hedberge319d2e2012-01-15 19:51:59 +02007787 memcpy(ev->eir, eir, eir_len);
Johan Hedberge17acd42011-03-30 23:57:16 +03007788
Johan Hedberg1dc06092012-01-15 21:01:23 +02007789 if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
7790 eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007791 dev_class, 3);
Johan Hedberg1dc06092012-01-15 21:01:23 +02007792
Jakub Pawlowski48f86b72015-03-04 16:24:24 -08007793 if (scan_rsp_len > 0)
Marcel Holtmannb487b9c2014-12-05 10:55:57 +01007794 /* Append scan response data to event */
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007795 memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
Jakub Pawlowski4b0e0ce2015-02-01 23:07:55 -08007796
Johan Hedberg5d2e9fa2014-03-25 10:30:47 +02007797 ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
7798 ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
Andre Guedesf8523592011-09-09 18:56:26 -03007799
Marcel Holtmann901801b2013-10-06 23:55:51 -07007800 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL);
Johan Hedberge17acd42011-03-30 23:57:16 +03007801}
Johan Hedberga88a9652011-03-30 13:18:12 +03007802
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007803void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
7804 u8 addr_type, s8 rssi, u8 *name, u8 name_len)
Johan Hedberga88a9652011-03-30 13:18:12 +03007805{
Johan Hedbergb644ba32012-01-17 21:48:47 +02007806 struct mgmt_ev_device_found *ev;
7807 char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2];
7808 u16 eir_len;
Johan Hedberga88a9652011-03-30 13:18:12 +03007809
Johan Hedbergb644ba32012-01-17 21:48:47 +02007810 ev = (struct mgmt_ev_device_found *) buf;
Johan Hedberga88a9652011-03-30 13:18:12 +03007811
Johan Hedbergb644ba32012-01-17 21:48:47 +02007812 memset(buf, 0, sizeof(buf));
Johan Hedberga88a9652011-03-30 13:18:12 +03007813
Johan Hedbergb644ba32012-01-17 21:48:47 +02007814 bacpy(&ev->addr.bdaddr, bdaddr);
Andre Guedes57c14772012-04-24 21:02:50 -03007815 ev->addr.type = link_to_bdaddr(link_type, addr_type);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007816 ev->rssi = rssi;
7817
7818 eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE, name,
Gustavo F. Padovan04124682012-03-08 01:25:00 -03007819 name_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007820
Marcel Holtmanneb55ef02012-03-14 18:08:46 +02007821 ev->eir_len = cpu_to_le16(eir_len);
Johan Hedbergb644ba32012-01-17 21:48:47 +02007822
Marcel Holtmann9cf12ae2013-10-06 23:55:52 -07007823 mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL);
Johan Hedberga88a9652011-03-30 13:18:12 +03007824}
Johan Hedberg314b2382011-04-27 10:29:57 -04007825
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007826void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
Johan Hedberg314b2382011-04-27 10:29:57 -04007827{
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007828 struct mgmt_ev_discovering ev;
Johan Hedberg164a6e72011-11-01 17:06:44 +02007829
Andre Guedes343fb142011-11-22 17:14:19 -03007830 BT_DBG("%s discovering %u", hdev->name, discovering);
7831
Johan Hedbergf963e8e2012-02-20 23:30:44 +02007832 memset(&ev, 0, sizeof(ev));
7833 ev.type = hdev->discovery.type;
7834 ev.discovering = discovering;
7835
Marcel Holtmann2f1e0632013-10-06 23:55:53 -07007836 mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
Johan Hedberg314b2382011-04-27 10:29:57 -04007837}
Antti Julku5e762442011-08-25 16:48:02 +03007838
Marcel Holtmann1904a852015-01-11 13:50:44 -08007839static void adv_enable_complete(struct hci_dev *hdev, u8 status, u16 opcode)
Marcel Holtmann5976e602013-10-06 04:08:14 -07007840{
7841 BT_DBG("%s status %u", hdev->name, status);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007842}
7843
7844void mgmt_reenable_advertising(struct hci_dev *hdev)
7845{
7846 struct hci_request req;
7847
Marcel Holtmannd7a5a112015-03-13 02:11:00 -07007848 if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
Marcel Holtmann5976e602013-10-06 04:08:14 -07007849 return;
7850
7851 hci_req_init(&req, hdev);
7852 enable_advertising(&req);
Johan Hedberg0ec5ae82014-07-08 15:07:50 +03007853 hci_req_run(&req, adv_enable_complete);
Marcel Holtmann5976e602013-10-06 04:08:14 -07007854}
Johan Hedberg6d785aa32015-03-06 21:08:51 +02007855
7856static struct hci_mgmt_chan chan = {
7857 .channel = HCI_CHANNEL_CONTROL,
7858 .handler_count = ARRAY_SIZE(mgmt_handlers),
7859 .handlers = mgmt_handlers,
7860};
7861
7862int mgmt_init(void)
7863{
7864 return hci_mgmt_chan_register(&chan);
7865}
7866
7867void mgmt_exit(void)
7868{
7869 hci_mgmt_chan_unregister(&chan);
7870}